Js类型判断

170 阅读2分钟

typeof

typeof 是一元操作符,放在其单个操作数的前面,操作数可以是任意类型。返回值为表示操作数类型的一个字符串。

typeof功能范围

typeof可以正确判断除了null之外的所有基本类型,而对于引用类型,除了函数外其他都会被判断为object

typeof null // 'object'
typeof undefined; // "undefined"
typeof false; // "boolean"
typeof 1; // "number"
typeof '1'; // "string"
typeof {}; // "object" 
typeof []; // "object" 
typeof new Date(); // "object"

typeof Symbol(); // "Symbol"
typeof 123n // 'bigint'

typeof原理

不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。

instanceof

通俗一些讲,instanceof 用来比较一个对象是否为某一个构造函数的实例。注意,instanceof运算符只能用于对象,不适用原始类型的值。

instanceof功能范围

instanceof无法判断基本类型,但可以正确判断引用类型。

// 输出 false
console.log('菲菲' instanceof String)

// 输出 true
console.log(new Date() instanceof Date)

instanceof原理

object instanceof constructor :检测 constructor.prototype是否存在于参数 object的 原型链上。

手写instanceof

/**
  自定义instanceof 
*/
function instanceOf(left, right) {
  let proto = left.__proto__
  while(proto){
    if(proto === right.prototype){
       return true
    }
    proto = proto.__proto__
  }  
  return false
}

class A{}
class B extends A {}
class C{}

const b = new B()
// 输出 true
console.log(instanceOf(b,B))
// 输出 true
console.log(instanceOf(b,A))
// 输出 false
console.log(instanceOf(b,C))

Object.prototype.toString

// 以下是11种:
var number = 1;          // [object Number]
var string = '123';      // [object String]
var boolean = true;      // [object Boolean]
var und = undefined;     // [object Undefined]
var nul = null;          // [object Null]
var obj = {a: 1}         // [object Object]
var array = [1, 2, 3];   // [object Array]
var date = new Date();   // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g;          // [object RegExp]
var func = function a(){}; // [object Function]

function checkType() {
    for (var i = 0; i < arguments.length; i++) {
        console.log(Object.prototype.toString.call(arguments[i]))
    }
}

checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func)

除了以上 11 种之外,还有:

console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(JSON)); // [object JSON]

除了以上 13 种之外,还有:

function a() {
    console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
}
a();

所以我们可以识别至少 14 种类型,当然我们也可以算出来,[[class]] 属性至少有 12 个。

根据对象的constructor属性判断

constructor 判断方法跟instanceof相似,但是constructor检测Object与instanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型。

constructor属性,可以得知某个实例对象,到底是哪一个构造函数产生的。

constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。所以,修改原型对象时,一般要同时修改constructor属性的指向。

console.log('22'.constructor === String)             // true
console.log(true.constructor === Boolean)            // true
console.log([].constructor === Array)                // true
console.log(document.constructor === HTMLDocument)   // true
console.log(window.constructor === Window)           // true
console.log(new Number(22).constructor === Number)   // true
console.log(new Function().constructor === Function) // true
console.log((new Date()).constructor === Date)       // true
console.log(new RegExp().constructor === RegExp)     // true
console.log(new Error().constructor === Error)       // true

注意:

1.null和undefined没有constructor;

2.判断数字时使用(),比如 (123).constructor,如果写成123.constructor会报错

3.constructor在类继承时会出错,因为Object被覆盖掉了,检测结果就不对了

   //注意当出现继承的时候,使用constructor会出现问题
    function A() {};
 
    function B() {};
    A.prototype = new B(); //A继承自B
    console.log(A.constructor === B)  -------->false
    var C = new A();
    //现在开始判断C是否跟A的构造器一样
    console.log(C.constructor === B)  -------->true
    console.log(C.constructor === A)  -------->false 
    //解决这种情况,通常是手动调整对象的constructor指向
    C.constructor = A; //将自己的类赋值给对象的constructor属性
    console.log(C.constructor === A);  -------->true
    console.log(C.constructor === B);  -------->false

参考:

JavaScript专题之类型判断(上)

JavaScript专题之类型判断(下)

typeof和instanceof原理

聊一聊typeof instanceof 实现原理

浅谈 instanceof 和 typeof 的实现原理