The original link
preface
In ES5, there are five basic data types: undefined, NULL, Boolean, number, string. In ES6, there is a new basic data type: Symbol. Typeof is the most commonly used javascript native built-in operator for determining data types in our development, but it has limitations.
The typeof operator
Grammar:
Typeof operator followed by operand:
typeof${operand}// or
typeof(${operand})Copy the code
Example:
typeof(undefined); // undefined
typeof(null); // object
typeof(true); // boolean
typeof(1); // number
typeof(' '); // string
typeof(Symbol(1)); // symbol
typeof(function () {}); // function
typeof([]); // object
typeof({}); // object
typeof(new Date()); // object
typeof(/abc/ig); // object
typeof(Math); // object
typeof(new Error('error')); // object
Copy the code
There are two things to note here:
typeof null
Will returnobject
. In the original version of JS, the 32-bit system was used to store the type information of variables in the low order for performance reasons. The beginning of 000 represents an object, while null represents all zeros. Therefore, it was wrongly identified as object, which was adopted by ECMAScript.typeof
You can’t tell exactly what the object type is. For example,typeof {}
.typeof new Date()
.typeof /abc/ig
.typeof Math
, both returnobject
Is it possible to tell us that this is adate
Object, that’s oneregexp
Objects? . And one of the things I can’t stand is,typeof []
Is returnedobject
. A lot of times in our business we want to be able to distinguish exactly what isarray
orobject
.
In addition, instanceof can also determine the type of an object, because the internal mechanism is to determine whether the prototype of the type can be found in the prototype chain of the object. However, this does not apply to some basic data types.
1 instanceof Number; // false
var num = new Number(1);
num instanceof Number; // true
Copy the code
thinking
Given typeof and Instanceof’s limitations, is there a relatively accurate way to determine data types? The answer is yes, it is the Object. The prototype. ToString. Call (XXX) method, the result returns to format form such as: [Object Array], [Object RegExp], [Object Date], etc. We can tell exactly what type of data the expression is based on the second word in parentheses in the return result. There is a lot of information on the web about how to use this function, and it can be represented in a variety of ways:
1. Object.prototype.toString.call(xxx);
2. ({}).toString.call(xxx);
3.[].toString.call(xxx); .Copy the code
In fact, no matter how many ways to write it, it also changes. Both call the native toString method on the prototype chain to cast the data type.
practice
The scene of a
If only six basic data types were needed, and function, array, and object were all that was needed, we could do this:
var superTypeof = function (val) {
var ans = typeof val;
if (ans === 'object') {
if (val === null) {
ans = 'null';
} else if (Array.isArray(val)) {
ans = 'array'; }}return ans;
}
Copy the code
IsArray (val) : val instanceof Array
test
superTypeof(undefined); // undefined
superTypeof(null); // null
superTypeof(true); // boolean
superTypeof(1); // number
superTypeof(' '); // string
superTypeof(Symbol(1)); // symbol
superTypeof(function () {}); // function
superTypeof([]); // array
superTypeof({}); // object
superTypeof(new Date()); // object
superTypeof(/abc/ig); // object
superTypeof(Math); // object
superTypeof(new Error('error')); // object.Copy the code
Scenario 2
One day, we realized that the superTypeof function above could not tell us exactly whether the Object type returned was Date, RegExp, or some other more specific Object. This time, we need to use the above mentioned Object. The prototype. ToString. Call (XXX) method.
var superTypeof = function (val) {
var ans = typeof val;
if (ans === 'object') {
ans = ({}).toString.call(val).slice(8.- 1).toLowerCase();
}
return ans;
}
Copy the code
Testing:
superTypeof(undefined); // undefined
superTypeof(null); // null
superTypeof(true); // boolean
superTypeof(1); // number
superTypeof(' '); // string
superTypeof(Symbol(1)); // symbol
superTypeof(function () {}); // function
superTypeof([]); // array
superTypeof({}); // object
superTypeof(new Date()); // date
superTypeof(/abc/ig); // regexp
superTypeof(Math); // math
superTypeof(new Error('error')); // error.Copy the code
In this way, we can accurately determine the data type in JS.
JQuery implementation
Let’s look at how jquery implements similar functionality:
var class2type = {},
typeStr = "Boolean Number String Function Array Date RegExp Object Error Symbol";
typeStr.split("").forEach(function (item) {
class2type[ "[object " + item+ "]" ] = item.toLowerCase();
});
var toType = function (obj) {
if ( obj == null ) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call( obj ) ] || "object" :
typeof obj;
}
Copy the code
Do you think the same implementation is not even good enough for me to write elegantly? This is not what the authors of jQuery intended.
Finally, I would like to create a powerful and lean library typeof2 from Amway that has similar features.