typeof

Generally used to determine basic data types, used to determine unexpected errors when referencing data types and null

Advantages: Good for determining base data (except for NULL)

Disadvantages: It is inaccurate to judge the referenced data type, for example, array type is judged as object type

Principle: Different objects are represented as binary at the bottom. In JS, the first three bits of binary are all zeros, which will be judged as object type. The binary of null represents all zeros (corresponding to the null pointer of machine code, which is generally all zeros), so it will be judged as object type.

typeof 1 // number
typeof '1' // string
typeof true // boolean
typeof Symbol('1') // symbol
typeof undefined // undefined

typeof function(){} // function
typeof { a: 1 } // object
typeof [1.2.3] Array.isArray is recommended to distinguish arrays from objects

// Exceptions are also judged below
typeof new Boolean(true) = = ='object';
typeof new Number(1) = = ='object';
typeof new String('abc') = = ='object';

// Finally, null
typeof null // object
Copy the code

instanceof

Its main function is to determine whether an instance belongs to a certain type, used to determine the object is appropriate

Advantages: Good for determining inheritance relationships and reference data types

Disadvantages: Cannot be used to determine the underlying data type because the underlying data type has no __proto__ attribute

Principle: Use __proto__ and prototype attributes for comparison

Grammar: objectinstanceof constructor 
objectAn instance objectconstructorA constructor 'abc' instanceof String //falseThe check prototype chain will returnundefined
new String('abc') instanceof String //true
new Boolean(true) instanceof Boolean // true 
new Number(1) instanceof Number // trueAnd by the way, let's do a simple implementationfunction new_instance_of(leftVaule, rightVaule) { 
    let leftProto = leftVaule.__proto__; // Take the __proto__ value of the left expression
    let rightPrototype = rightVaule.prototype; // Take the prototype value of the right expression
   
    while (true) {
    	if (leftProto === null) {
            return false;	
        }
        if (rightPrototype === rightProto) {
            return true;	
        } 
        leftProto = leftProto.__proto__ 
    }
}

Copy the code

constructor

The constructor returns the type according to the data type

Advantages: The judgment of inheritance relation and data type is relatively standard

Disadvantages: Null and undefined have no constructors and can cause injudgment

Principle: Use the constructor attribute to judge

' '.constructor == String    //true  
new Number(1).constructor == Number   //true  
new Function().constructor == Function  //true 
true.constructor == Boolean   //true
new Date().constructor == Date  //true
Copy the code

Object.prototype.toString.call()

You can get the type of each object by toString(). To every Object through the Object. The prototype. The toString () to test, need to Function. The prototype. The call () or the Function. The prototype, the apply () in the form of a call, Pass the object to be checked as the first argument.

Advantages: The browser’s built-in data types can be accurately determined

Disadvantages: Cannot determine the inheritance relationship, any instance will be returned as object

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]

toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
Copy the code

Lodash. BaseGetTag and lodash. GetTag

Lodash. baseGetTag is used to determine the built-in data type of the browser

BaseGetTag use Object. The prototype. ToString. Call and Symbol toStringTag to determine the type of the property

// lodash.basegetTag

	// If the value is undefined and null, the corresponding tag is returned
     if (value == null) {
        return value === undefined ? 
  				'[object Undefined]' 
  				: 
  				'[object Null]'
      }
     // If Symbol is not supported or value is not attached to Symbol. ToStringTag,
     / / returns Object directly. The prototype. ToString value after the call
      if(! (symToStringTag && symToStringTagin Object(value))) {
        return toString.call(value)
      }

Copy the code

Lodash.gettag uses baseGetTag and constructor to determine the type of an attribute. Mainly used to do the compatibility processing of the following types of judgment (DateView, Map, Promise, Set, WeakMap, etc.)

//lodash.getTag part of the important source code

// If in some circumstances it is not possible to identify the five types, do compatibility processing
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
        (getTag(new Map) != mapTag) ||
        (getTag(Promise.resolve()) ! = promiseTag) || (getTag(new Set) != setTag) ||
        (getTag(new WeakMap) != weakMapTag)) {
      baseGetTag = (value) = > {
            const result = baseGetTag(value)
            const Ctor = result == '[object Object]' ? value.constructor
            							   : undefined;						
            const ctorString = Ctor ? `${Ctor}` : ' '
            // Get the constructor attribute of the value, return the corresponding tag if obtained,
            // Return the original toString value if it cannot be retrieved
            if (ctorString) {
              switch (ctorString) {
                case dataViewCtorString: return dataViewTag
                case mapCtorString: return mapTag
                case promiseCtorString: return promiseTag
                case setCtorString: return setTag
                case weakMapCtorString: return weakMapTag
              }
            }
            return result
  }
}

Copy the code