May 30, 2021 Article blog
In the ECMAScript specification, a total of seven data types are defined, divided into basic types and reference types, as follows:
Basic types: String, Number, Boolean, Symbol, Undefined, Null Reference Type: Object
The basic type, also known as a simple type, is a simple segment of data that, because it occupies a fixed space, is stored in the stack, i.e. accessed by value, in order to facilitate the speed of variable queries.
Reference types, also known as complex types, cannot be stored in a stack because the size of their values changes, otherwise they slow down variable queries, so their values are stored in the heap, and the values stored at the variables are pointers to the memory of the stored object, i.e. accessed on a per-site basis. In addition to Object, reference types include Function, Array, RegExp, Date, and so on.
Since ECMAScript is loosely typed, there is a need for a means of detecting the data type of a given variable. JavaScript also provides a variety of methods for this problem, but unfortunately the results from different approaches vary.
Here are four commonly used methods and a brief analysis of the problems with each method.
Typeof is an operator that follows a monary expression to the right and returns the data type of the expression. The results returned are expressed as strings of this type (all lowercase letters) and include the following 7 categories: number, boolean, symbol, string, object, undefined, function, and so on.
typeof';/string is valid
typeof1;/number is valid
typeofSymbol();/symbol is valid
typeoftrue;//boolean is valid
typeofundefined;//undefined is valid
typeofnull;/object is invalid
typeof.//object is not valid
typeofnewFunction();/function is valid
typeofnewDate(); //object is invalid
typeofnewRegExp(); //object is invalid
Sometimes the typeof operator returns some confusing but technically correct values:
Where null has its own data type Null, the array, date, and regular in the reference type all have their own specific types, and typeof for these types of processing, only returns the Object type at the top of its prototype chain, no error, but not the result we want.
instanceof is an instance that determines whether A is B, the expression is: A instanceof B, and if A is an instance of B, returns true, otherwise false is returned. It is important to note here that instanceof detects a prototype, and we simulate its internal execution with a piece of pseudo-code:
instanceof (A,B) = {
varL = A.__proto__;
varR = B.prototype;
if(L === R) {
The internal property of A __proto__ prototype object that points to B
returntrue;
}
returnfalse;
}
As you can see from the above process, when A's proto points to B's prototype, it is considered an instance of B, and let's look at a few more examples:
[] instanceof Array;// true
{} instanceof Object;// true
newDate() instanceof Date;// true
function Person(){};
newPerson() instanceof Person;
[] instanceof Object;// true
newDate() instanceof Object;// true
newPerson instanceof Object;// true
We've found that while instanceof can tell that it's an instance of Array, it thinks it's also an instance of Object, so why?
Let's analyze the relationship between the three:
From the instanceof, it can be determined that the .proto points to Array.prototype, while Array.prototype.proto points to Object.prototype, and finally Object.prototype.proto points to null, marking the end of the prototype chain. As a result, a prototype chain has been formed within the company:
As you can see from the prototype chain, the proto of is directed directly to Array.prototype and indirectly to Object.prototype, so according to the judgment rules of instanceof, this is an example of Object. B y analogy, similar new Date() and new Person() form a corresponding prototype chain. Therefore, instanceof can only be used to determine whether two objects belong to an instance relationship, not what type an object instance belongs to.
The problem with the instanceof operator is that it assumes only one global execution environment. I f a Web page contains more than one framework, there are actually more than two different global execution environments, resulting in more than two different versions of the constructor. If you pass an array from one frame to another, the incoming array has different constructors than the array natively created in the second frame.
variframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[0]. Array;
vararr =newxArray(1,2,3);// [1,2,3]
arr instanceof Array;// false
if(Array.isArray(value)){
Do something with the array
}
Array.isArray() essentially detects the value of the object, which is an internal property of the object that contains the type information of the object in the format of "object Xxx", which is the specific type. For an array, the value of the value of the class is the value of the object Array.
When a function F is defined, the JS engine adds a prototype prototype to the F prototype, and then adds a constructor property to the prototype, which points to a reference to F. Here's what it looks like:
F is treated as a constructor when var f is new F(), f is an instance object of F, and the constructor on the F prototype is passed to f, so f.constructor is F
As you can see, F refers to itself using the constructor on the prototype object, and when F creates the object as a constructor, the constructor on the prototype is inherited to the newly created object, which is the type of the new object from the prototype chain point of view. The point is that new objects have traceable data types after they are born.
Similarly, built-in objects in JavaScript do this when built internally:
Details:
null and undefined are invalid objects, so there will be no constructor, and both types of data need to be judged in other ways. 2. The constructor of the function is unstable, which is mainly reflected in the custom object, when the developer rewrites the prototype, the original constructor reference is lost, and the constructor defaults to Object
Why object?
Because the prototype is re-assigned to a literal amount of the new Object(), the new Object() passes the constructor on the Object prototype to the object itself.
Therefore, in order to standardize development, it is generally necessary to re-assign the constructor when rewriting the object prototype to ensure that the type of the object instance is not tampered with.
ToString() is the prototype method of Object, which is called and returns the current object by default. This is an internal property in the form of object Xxx, where Xxx is the type of object.
For object objects, calling toString() directly returns the object object. For other objects, calls are required to return the correct type information.
Object.prototype.toString.call('') ; [object String]
Object.prototype.toString.call(1) ; [object Number]
Object.prototype.toString.call(true) ;// [object Boolean]
Object.prototype.toString.call(Symbol());//[object Symbol]
Object.prototype.toString.call(undefined) ;// [object Undefined]
Object.prototype.toString.call(null) ;// [object Null]
Object.prototype.toString.call(newFunction()) ;// [object Function]
Object.prototype.toString.call(newDate()) ;// [object Date]
Object.prototype.toString.call([]) ;// [object Array]
Object.prototype.toString.call(newRegExp()) ;// [object RegExp]
Object.prototype.toString.call(newError()) ;// [object Error]
Object.prototype.toString.call(document) ;// [object HTMLDocument]
Object.prototype.toString.call (window);//object global window is a reference to the global object