preface
JS variables are very different from variables in other languages because their loose nature determines that a variable is just a name used to store a specific value for a specific period of time. The value of a variable and its data type can change during the declaration cycle.
JS data types can be divided into basic types and reference types. Firstly, two types of data types are briefly introduced, and then several methods of judging data types are analyzed. Of course, this is also a common interview question, students can answer and expand according to the ideas of the article, so that the interviewer find everything new and fresh.
The data type
Basic types of
The basic types include Undefined, Null, String, Number, Boolean, and Symbol. Basic types are accessed by value, so we can manipulate the actual value stored in the variable.
Values of basic types occupy a fixed amount of memory and are stored in stack memory. Copying a value of a primitive type from one variable to another creates a copy of that value, and the two values are stored completely independently in stack memory.
Reference types
Reference types are Object types, including Object, Array, Function, Data, Regexp, and Error. The value of a reference type is an object stored in heap memory. JS does not allow direct access to the location in memory, that is, the memory space of the operation object cannot be accessed directly.
When you manipulate an object, you are actually manipulating its reference, so the value of a reference type is accessed by reference. [1, 2] === [1, 2] is false.
Determine the data type
After a brief talk about the two kinds of DATA types of JS, the next introduction to JS judge the data type of 4 methods.
typeof
Typeof is the best tool for determining whether a variable is string, number, Boolean, symbol(a new type in ES6), or undefined. Note that null and referential data are not mentioned here.
Typeof may return one of the following results, corresponding to the following values:
- Undefined: undefined value
- String: string
- Number: numerical
- Boolean: the Boolean
- Symbol: unique value
- object: object or null value (
null
) - Function: the function
typeof undefined; // undefined
typeof null; // object
typeof "This is a string."; // string
typeof 1; // number
typeof true; // boolean
typeof new Symbol(a);// symbol
typeof new Object(a);// object
typeof new Function(a);// function
typeof new Date(a);// object
Copy the code
In the above example, all but NULL returns the correct result for primitive types. Calling Typeof NULL returns object because NULL is considered an empty object reference and therefore returns object. This is also a Bug from the early days of the JS design language.
All reference types except function return object. Therefore, using typeof to determine the typeof reference type data is not recommended. Typeof is suitable for determining underlying type values.
instanceof
Instanceof is used to determine whether an instance object belongs to A constructor. The expression A instanceof B returns true if A is an instanceof B, and false otherwise.
In fact, the implementation principle is to find whether there is A prototype equal to B. protoType on the prototype chain of A, if the top of the prototype chain is always found null, still can not find the prototype equal to B.prototype, then can return false. The knowledge of prototype chains can be reviewed in the previous article, “The Torture of prototype and prototype chains”, oh, I will not talk about prototype chains here
new Date(a)instanceof Date; // true
new Date(a)instanceof Object; // true
[] instanceof Array; // true
[] instanceof Object; // true
function Person() {};
const person = new Person();
person instanceof Person; // true
person instanceof Object; // true
Copy the code
As you can see from the above example, instanceof determines that [] is an instanceof Array, that Date Object is an instanceof Date, and that person is an instanceof the person constructor. There is no problem here, but instanceof assumes that these are also instances of Object, which is a bit confusing.
In fact, instanceof can be analyzed according to the implementation principle, the implementation principle has been described above, here we apply instanceof for array judgment process.
[] instanceof Array: [].__proto__ refers to array. prototype, so returns true. [].__proto__ refers to array. prototype. Array.prototype is an instanceof Object by default. Array.prototype.__proto__ refers to object. prototype, so that’s why instanceof thinks [] is also an instanceof Object.
Instanceof can only be used to determine whether two objects belong to an instance relationship, not what type an object belongs to. Simply put, it is to determine whether two classes are dependent.
The problem with Instanceof is that if there is only one global execution environment, if there are two frames in a web page, there are actually two different global execution environments, and therefore two different versions of the Array constructor. If you pass an array from one framework to another, the array passed in is a different constructor than the array created natively in the second framework.
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const IArray = window.frames[0].Array;
const iarr = new IArray();
iarr instanceof Array; // false
Array.isArray(iarr); // true
Copy the code
To solve this problem, ES5 added array.isarray (), a method that determines whether a value is an Array or a class Array.
constructor
In the prototype chain mentioned above, the constructor property of the prototype object points to the constructor, and since the __proto__ property of the instance object points to the prototype object, it can have: each instance object has access to its constructor via constructor. The JS built-in objects do the same when built internally and can therefore be used to determine data types.
"".__proto__.constructor === String; // true
// If __proto__ is removed, the effect is the same
"".constructor === String; // true
new Number(1).constructor === Number; // true
true.constructor === Boolean; // true
[].constructor === Array; // true
new Date().constructor === Date; // true
new Function().constructor === Function; // true
Copy the code
As you can see, most types can be determined by this attribute. But since undefined and NULL are invalid objects and therefore have no constructor attribute, these two values cannot be determined in this way. In addition, when a prototype is rewritten, its original constructor is lost and the judgment is invalidated.
function Person() {};
Person.prototype = {
name: "XX"
};
const person = new Person();
person.constructor === Person; // false
Copy the code
Type Person. constructor and see that it is an Object. Why is it Object? This is because when the prototype is redefined, an Object {} is passed in. {} is the literal of new Object(), so constructor from the Object prototype is passed to {}, so Person. constructor prints out Object.
Therefore, whenever you rewrite a prototype object, you need to reassign constructor to ensure that the type of the object instance does not change. Remember to pay attention to this point when developing!
toString
Object. The prototype. The toString method returns the Object type string, and therefore can be used to judge the type of a value. For instance objects may be custom toString method, will cover the Object prototype. ToString, therefore, when using, had better add call. The following values are returned
[object Undefined]
: Undefined value[object Null]
: a null value[object String]
String:[object Number]
: numerical[object Boolean]
: Boolean[object Symbol]
The only value:[object Object]
Object:[object Array]
An array of:[object Function]
: function[object Date]
Date:[object RegExp]
: regular[object Error]
Error:
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call("This is a string."); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call({}); // [object Object]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]
Copy the code
Summary and comparison
typeof
Simple to use, but only for judgmentThe base typedatainstanceof
Can determine reference types, cannot detect base types, and cannotAcross the iframe useconstructor
Pretty much any type, exceptnullandundefined, but constructor is easily modified and cannot be used across iframestoString
It can judge all types, so it can be encapsulated into an omnipotentDataType()
Determine all data types
function DataType(tgt, type) {
const dataType = Object.prototype.toString.call(tgt).replace(/\[object (\w+)\]/."$1").toLowerCase();
return type ? dataType === type : dataType;
}
DataType("young"); // "string"
DataType(20190214); // "number"
DataType(true); // "boolean"
DataType([], "array"); // true
DataType({}, "array"); // false
Copy the code
conclusion
The four judgment methods of JS have their own advantages and disadvantages, and appropriate judgment methods should be adopted according to the specific situation. So arrive here, have what write wrong return troublesome everybody big guy points out. I will continue to write better articles with your support