如上是我最近刷题遇到的一个小坑,可以看到用typeof判断null的类型时,返回的是一个’object’,而用instanceof判断时返回的是false,但不知道具体原因。于是重新再学习该部分内容并归纳总结。
typeof
typeof 的数据类型
typeof 运算符不是变量。它属于运算符。运算符(比如 + - * /)没有数据类型。
但是,typeof 始终会返回字符串(包含运算数的类型)。
typeof 操作符返回一个字符串,表示未经计算的操作数的类型。
我们可以利用 typeof 来判断number, string, object, boolean, function, undefined, symbol
这七种类型,这种判断能帮助我们搞定一些问题,比如在判断不是 object 类型的数据的时候,typeof能比较清楚的告诉我们具体是哪一类的类型。但是,很遗憾的一点是,typeof 在判断一个 object的数据的时候只能告诉我们这个数据是 object, 而不能细致的具体到是哪一种 object
例如:
let a = new String('abc');
typeof a === 'object'// true
a instanceof String // true
实现原理
js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息
000:对象
010:浮点数
100:字符串
110:布尔
1:整数
但是, 对于 undefined 和 null 来说,这两个值的信息存储是有点特殊的。
null:所有机器码均为0
undefined:用 −2^30 整数来表示
所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
构造函数通过new可以实例对象,instanceof 能判断这个对象是否是之前那个构造函数生成的对象
例如:
// 定义构建函数
let Car = function() {}
let benz = new Car()
benz instanceof Car // true
let car = new String('xxx')
car instanceof String // true
let str = 'xxx'
str instanceof String // false
实现原理
顺着原型链去找,直到找到相同的原型对象,返回true,否则为false。
区别及使用
区别如下:
typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值;
instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断。
所以可以采用Object.prototype.toString
,调用该方法,统一返回格式“[object Xxx]”
的字符串,如:
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([]) //"[object Array]"
还有大佬利用toString
的基本用法,实现了一个全局通用的数据类型判断方法
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}
使用:
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回