The typeof operator

The typeof operator returns the typeof the parameter. This is useful when we want to process values of different types separately, or when we want to do quick data type checking. It supports two syntactic forms:

  • As operator: typeof X.
  • Function form: typeof(x)

Parentheses are sometimes necessary, but if you don’t add them you won’t get the result you want because of the priority. Such as:

typeof 'string'= = =true; // false
typeof ('string'= = =true); // "boolean"
Copy the code

A call to Typeof X returns the data type as a string:

typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol" 

typeof Math // "object" (1) // Any other object

typeof null // "object" (2)

typeof alert // "function" (3) // function object
Copy the code

The last three lines may require additional clarification:

  1. Math is a built-in object that provides mathematical operations.
  2. The result of typeof NULL is “object”. This is an officially acknowledged typeof behavior error, a problem that dates back to the early days of the JavaScript language and has been preserved for compatibility. Null is definitely not an object. Null has its own type, which is a special value.
  3. The result of typeof Alert is “function”, because alert is a function in the JavaScript language. There is no special “function” type in the JavaScript language. Functions belong to type object. But Typeof treats functions differently and returns “function”. This is also a problem from the early days of the JavaScript language. This behavior is technically incorrect, but it is very convenient in real programming.

In addition, when Typeof processes a wrapper type, it returns the corresponding original data type. But it’s not recommended. Such as:

        typeof Number(1); // "number"
        typeof Boolean(true); // "boolean"
        typeof String('string'); // "string"
Copy the code

The Typeof operator treats the Object and Function types differently

Technically, functions are objects in ECMAScript, not data types. However, functions do have some special properties, so it is necessary to distinguish functions from other objects through typeof operators.

Typeof operator handling of NULL

This bug is left over from the first version of Javascript. In Javascript, different objects are represented as binary at the bottom level. However, in Javascript, each data type is represented by three bits.

  • 000 indicates the data of Object type.
  • 001 indicates data of the Int type.
  • 010 represents data of type Double.
  • 100 indicates String data.
  • 110 represents Boolean data.

Since null represents a null pointer (the median value on most platforms is 0x00), null’s type label becomes 0, so ‘object’ is returned when typeOF is executed.

The instanceof operator

Determine whether a variable is an array or an object

First we try to test with the Typeof operator.

	const arr = [0.1.2];
	console.log(typeof arr) // "object"
Copy the code

We find that the output is “object”, which is not what we expected. So using the Typeof operator does not directly determine whether a variable is an object type or an array type. In fact, the Typeof operator can be useful for determining basic data types, but it can be difficult to determine reference municipal types.

Next, let’s try to test with the Instanceof operator.

The instance operator is used to detect whether a variable is an instance of a type of data by looking up the stereotype chain. Use the instanceof operator to determine whether a variable is an array or an object.

        const a = [0.1.2];
        console.log(a instanceof Array); // true
        console.log(a instanceof Object); // true

        const b = {name: 'xx'};
        console.log(b instanceof Array); // false
        console.log(b instanceof Object); // true
Copy the code

Note that A is also a member of the Object class. Because, prototypically, Array inherits from Object. Instanceof takes the prototype chain into account in its checks. So when we decide whether a variable is an array or an object, we should first determine the type of the array and then the type of the object. If the object is judged first, then the array value is also judged as the object type, which is not sufficient.

We can get the following wrapper function.

        function getDataType (o) {
            if (o instanceof Array) return 'Array'
            if (o instanceof Object) return 'Object'
            return 'others'
        }
Copy the code

Another way to think about it is to judge the constructor

To determine whether a function is an Array or an object, on the other hand, is to determine whether the variable’s constructor is of type Array or Ojbect. Since an instance of an object is generated through a constructor, we can directly determine the constructor property of a variable.

        const a = [0.1.2];
        console.log(a.constructor === Array); // true
        console.log(a.constructor === Object);  // false

        const b = {name: 'xx'};
        console.log(b.constructor === Array); // false
        console.log(b.constructor === Object); // true
Copy the code

We can get the following wrapper function.

        function getDataType (o) {
            const constructor = o.__proto__.constructor || o.constructor
            if (constructor === Array) return 'Array';
            if (constructor= = =Object) return 'Object';
            return 'others'
        }
Copy the code

Object. The prototype. ToString function

Use the Object. The prototype. ToString. Call () method to reveal the type

Each reference type inherits directly or indirectly from the Object type, so they all contain the toString() function. ToString () returns different values for different data types, so the toString() function can be used to determine exactly what type the value is.

  • For the number type, the result is [object number]
  • For Boolean types, the result is [object Boolean]
  • For NULL: [object null]
  • For undefined: [object undefined]
  • For arrays: [object Array]
  • For objects: [object object]
  • … Etc. (customizable)

Symbol.toStringTag

You can customize the behavior of an object’s toString method using the special object attribute symbol.toStringTag.

let user = {
  [Symbol.toStringTag]: "User"
};
alert( {}.toString.call(user) ); // [object User]
Copy the code

So, if we want to get the type of the built-in object and want to return that information as a string rather than just checking the type, we can use {}.toString.call instead of instanceof.

conclusion