JS, as a weakly typed language, has many ways to judge types, and there are different ways to judge different types of data. This paper summarizes which scenarios apply which ways to judge.
JS
The data type
Before saying to judge the type, first summarize what data types JS has, generally divided into basic data types and reference data types.
Basic data types: NULL, undefined, String, number, Boolean, symbol, bigINT
Reference data types: Object, array, function
To be exact, JS has eight built-in types, namely seven basic data types and one reference data type object, such as Array, Date… These are called built-in objects.
Note: types begin with a lowercase letter, and constructors begin with an uppercase letter!!
typeof
Typeof Determines the basic data type
In general, typeof is used to determine basic data types:
let unde = undefined
typeof unde // "undefined"
typeof Madman // "undefined"
let str = 'Madman'
typeof str // "string"
let num = 1
typeof num // "number"
let boole = true
typeof boole // "boolean"
let sym = Symbol('id')
typeof sym // "symbol"
let bigi = 10n
typeof bigi // "bigint"
Copy the code
typeof null
Null = null; null = null;
let nu = null
typeof nu // "object"
Copy the code
why ?
There are books that say,
Null points to a pointer to an empty object, so Typeof judgment returns Object. “JavaScript Advanced Programming (Version 2)”
There are books that say,
In javascript, different objects are represented as binary objects at the bottom level. In javascript, the first three bits of the binary are considered as object objects, and the first three bits of the binary are all zeros, so the first three bits of the binary are also zeros. Therefore, ‘Object’ is returned when typeof is executed. Javascript you Don’t Know (Volume 1)
So you decide for yourself, and I’m not going to argue about it here, but how do you determine null?
let nu = null
nu === null // true
Copy the code
typeof number
In addition to null, there is another non-general, which is number. Although the above typeof num does return “number”, the following code also shows that it is non-generic.
let num = 1
typeof num // "number"
let na = NaN
typeof na // "number"
Copy the code
In JS NaN is a number itself, which is an abbreviation of Not a number. For example, NaN is returned when unexpected problems occur with the operator, such as:
2 * 'Madman' // NaN
typeof 5*1 // NaN
Copy the code
Because typeof takes precedence over the operator, the above is equivalent to (typeof 5) * 1;
typeof
Why can’t I determine the reference data type?
The first three digits of a null binary are all zeros. Therefore, if you use it to judge an object or an array, you will return an object. We have any good explanation can also share, here do not go too far.
typeof fn
Why returnfunction
?
Function (fn === ‘function’); function (fn === ‘function’);
Function is actually a “subtype” of Object. Specifically, functions are “callable objects.” — JavaScript volumes you don’t know
Well, again, the book says that =v=, so since it is defined as a callable object, it must be different from the object. If you look up the relevant information, you will find that,
Function is implemented according to the ECMA-262 specification [[Call]],
Does typeof return ‘function’ if it implements [[call]] internally? This argument here is no longer in-depth, for a browser has not studied the implementation principle of the porter, this is just my point of view, we have what good views can also be published, learn from each other.
Lowercase are types, uppercase are constructors. Make sure you understand that.
Typeof Number typeof String Typeof function Typeof Array Typeof Object typeof class A {} // Typeof Null typeof Undefined /** * returns' Undefined '. * null and undefined do not have constructors */Copy the code
Number. The isNaN (), isNaN ()
typeof + Number.isNaN()
Judge number types accurately
As mentioned above, Typeof cannot accurately judge whether a variable is a number type in our cognition, so now we can implement a number type that can accurately judge the number type in cognition through other ways.
function _isNum(num) { return typeof num === 'number' && ! Number.isNaN(num) }Copy the code
Number.isnan () : Used to determine if the value passed is a NaN and to check if it is of type Number
IsNaN () : is also used to determine whether a value isNaN. If the value passed is not of number type, number () is used to enforce this judgment. To try implementing a polyfill:
var isNaN = isNaN || function (v) { var n = Number(v) return n ! == n }Copy the code
One feature of NaN used above is that it is never equal to itself.
Implement a number.isnan () with isNaN() :
Number.isNaN = Number.isNaN || function(v) {
return typeof v === 'number' && isNaN(v)
}
Copy the code
instanceof
Used to determine whether the right-hand constructor exists on the prototype chain of the left-hand object instanceprototype
The principle of
let date = new Date()
date instanceof Date // true
date instanceof Object // true
let fn = () => {}
fn instanceof Function // true
fn instanceof Object // true
let arr = []
arr instanceof Array // true
arr instanceof Object // true
let o = {}
o instanceof Object // true
class A {}
let a = new A()
a instanceof A // true
a instanceof Object // true
class A_1 extends A {}
let a_1 = new A_1()
a_1 instanceof A_1 // true
a_1 instanceof A // true
a_1 instanceof Object // true
Copy the code
Using the above code to summarize the rules, let’s implement a simplified version of Instanceof:
Object.prototype._instanceof = function (constru) {
let consProto = constru.prototype
let currentProto = this.__proto__
while(true) {
if (currentProto === null) return false
if (currentProto === consProto) return true
currentProto = currentProto.__proto__
}
}
Copy the code
Note:Object.prototype.__proto__
Although supported by most browsers, and this property has beenES6
This property is standardized in the specification, but it is still not recommended in the specification, so we can use itObject.getPrototypeOf()
Instead of it.
whyinstanceof
Can’t tell the basic type?
Take a look at the following code:
let n = 2
n instanceof Number // false
n instanceof Object // false
let n_n = new Number(2)
n_n instanceof Number // true
n_n instanceof Object // true
let str = 'Madman'
str instanceof String // false
str instanceof Object // false
let str_str = new String('Madman')
str_str instanceof String // true
str_str instanceof Object // true
Copy the code
We know that there are two common ways to create variables: a literal and a constructor.
Variables that are declared directly by literals are called “primitive values.” Primitive values have no properties or methods and are boxed only when they are used. Therefore, instanceof is generally not used to determine this basic data type.
constructor
This property is mounted to Object.prototype and returns a reference to the constructor that created the instance Object.
let n = 2 n.constructor === Number // true let str = 'Madman' str.constructor === String // true let date = new Date() date.constructor === Date // true let fn = () => {} fn.constructor === Function // true let arr = [] arr.constructor === Array // true let o = {} o.constructor === Object // true class A = {} let a = new A() a.constructor === A // true class A_1 extends A {} let a_1 = new A_1() a_1.constructor === A_1 // true a_1.constructor === A // falseCopy the code
That sounds nice, but the biggest problem with this approach is that the constructor property of the string, number, and Boolean types is read-only, and the constructor property of any other type can be modified!! .
Let date = new date () date.constructor = () => {console.log(' I have been modified ')} date.constructor === date // falseCopy the code
Of course, no one usually has time to change it.
Array.isArray()
This function is used to determine whether an object is an array.
let arr = []
Array.isArray(arr) // true
Copy the code
When determining whether an object is an Array, use array. isArray rather than instanceof.
becauseinstanceof
andconstructor
Both are limited to top-level objects, while the former is not.
For example, if one page loads another page via iframe, the constructors of the two pages are not the same reference, because they belong to two top-level objects.
Although it’s not normally used that way.
Object.prototype.toString.call()
Each of the above judgments actually has its own advantages and disadvantages. We can judge each type in a relatively perfect way.
Object.prototype._isType = function(constructorStr) {
return Object.prototype.toString.call(this) === `[object ${constructorStr}]`
}
Copy the code