常用方法包括 typeof、instanceof、constructor 和 toString。
变量定义 1 2 3 4 5 6 7 8 9 let undefinedVlet boolV = true let numV = 9527 let strV = '9527' let symbolV = Symbol ('9527' )let nullV = null let arrV = [9 , 5 , 2 , 7 ]let objV = new Object ()let funcV = function ( ) {}
typeof typeof 用于确定值的原始类型 。
1 2 3 4 5 6 7 8 9 10 11 12 13 console .log (typeof undefinedV) console .log (typeof boolV) console .log (typeof numV) console .log (typeof strV) console .log (typeof symbolV) console .log (typeof nullV) console .log (typeof arrV) console .log (typeof objV) console .log (typeof funcV) class Parent {}class Child extends Parent {}let child = new Child ()
typeof 对原始类型变量以及 function 都能够正常判断,但是对于引用类型一律视作 Object,因此不能用来判断引用类型。
值得注意的是,typeof 对于 null 类型变量也会输出 'object',这是因为 JavaScript 最初使用低位存储变量类型信息,Object 类型变量的机器码标识低 3 位为 0,null 类型变量的机器码标识为全 0。typeof 进行类型判断时,直接根据机器码低位标识进行判断,导致二者识别结果重复(均为’000’),故使得 typeof null 输出为 'object'。
因为这个 bug 遗留太久了,因此后续也就没再修复,以免影响太大。
instanceof instanceof 用于确定对象 (引用值)的具体类型。
1 2 3 4 5 6 console .log (arrV instanceof Array ) console .log (objV instanceof Object ) console .log (funcV instanceof Function ) console .log (child instanceof Child ) console .log (child instanceof Parent )
instanceof 对变量原型链上所有对象都会返回 true。
instanceof 不能用于 null 和 undefined,会报错。
使用 instanceof 检测任何引用值与 Object 构造函数都会返回 true,例如 arrV instanceof Object === true
使用 instanceof 检测任何原始值都会返回 false,例如 boolV instanceof Object === false。
constructor 1 2 3 4 5 6 7 console .log (boolV.constructor === Boolean ) console .log (numV.constructor === Number ) console .log (strV.constructor === String ) console .log (symbolV.constructor === Symbol ) console .log (arrV.constructor === Array ) console .log (objV.constructor === Object ) console .log (funcV.constructor === Function )
undefined 和 null 没有 constructor 属性,因此不能用这个方法判断他俩。
constructor 指向可以被改变,因此这个方法不安全。
toString 准确来说是 Object.prototype.toString.call(variable)。
1 2 3 4 5 6 7 8 9 10 11 console .log (Object .prototype .toString .call (undefinedV)) console .log (Object .prototype .toString .call (boolV)) console .log (Object .prototype .toString .call (numV)) console .log (Object .prototype .toString .call (strV)) console .log (Object .prototype .toString .call (symbolV)) console .log (Object .prototype .toString .call (nullV)) console .log (Object .prototype .toString .call (arrV)) console .log (Object .prototype .toString .call (objV)) console .log (Object .prototype .toString .call (funcV)) console .log (Object .prototype .toString .call (child))
toString 输出类的 [[Class]] 属性,即构造函数名,但它无法检测非原生构造函数的构造函数名。
总结
typeof 适合判断原始变量类型,不适合判断引用变量类型和 null。
instanceof 适合判断引用变量的具体类型,不适合判断原始变量类型和 undefined、null。
constructor 能够判断原始变量类型和引用变量类型,但不能用于 undefined 和 null,且不够安全。
toString 能够判断所有原始变量类型和引用变量类型,比较全面,但不能判断非原生引用变量类型。
判断 undefined 可以用 typeof、toString;判断 null 可以用 toString;判断原生引用变量类型可以用 instanceof、constructor 和 toString;判断非原生引用变量类型可以用 instanceof,但需注意其对于变量原型链上所有对象均会返回 true。