typeof与instanceof的区别
typeof是一个一元运算符,用来获取一个变量的数据类型。它返回的是一个字符串,这字符串说明了变量的类型。可能输出包括:undefined、object、number、string、boolean、function、symbol、bigint,如下图:
值得注意的是:对null变量使用typeof 运算符会输出object,而对属于object的function变量则会输出function。
原理:js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息。而 typeof 关键字检测数据类型的原理就是通过检测这1-3位机器码实现检测不同数据类型。同时,在typeof 在检测出其为引用数据类型后,还会再检测这个引用数据类型是否有实现[[call]]方法。不是,则返回object ,是,则返回function。
而null变量的机器码为全零,object的机器码只有后三位为0,这就导致了typeof对null的检测结果为object。
instanceof 可以判断一个变量是否是某个构造函数的实例,但需要注意的是,基本类型是不能用 instanceof 来判断的,因为基本类型不是对象。
console.log("John" instanceof String); // 输出: false
console.log(6 instanceof Number); // 输出: false
console.log(true instanceof Boolean); // 输出: false
console.log(undefined instanceof Object); // 输出: false
console.log(null instanceof Object); // 输出: false
console.log({} instanceof Object); // 输出: true
console.log([] instanceof Array); // 输出: true
console.log(function(){} instanceof Function); // 输出: true
console.log(new String("John") instanceof String); // 输出: true
console.log(new Number(6) instanceof Number); // 输出: true
console.log(new Boolean(true) instanceof Boolean); // 输出: true
原理:按照原型链上查,即右边变量的prototype在左边变量的原型链上即可(也就是说左边的变量能在原型链上找到左边变量的prototype) 按照此原理,手写一下instanceOf吧
function myInstanceof(L,R) {
L = L.__proto__;
while(L != null) {
if(L === R.prototype) {
return true;
}
L = L.__proto__;
}
return false;
}
但是,如果修改了右边变量的protoType,则在左侧变量的原型链上无法找到,instanceof会返回false。
拓展:Object.prototype.toString.call() 推荐!
每一个继承 Object 的对象都有toString 方法,如果toString 方法没有重写的话,会返回[Object type],其中type 为对象的类型,值为[[Class]] 内部属性的值。
[[Class]] 内部属性的值可以是除了 “Arguments”, “Array”, “Boolean”, “Date”, “Error”, “Function”, “JSON”, “Math”, “Number”, “Object”, “RegExp”, “String” 的任何字符串。
console.log(Object.prototype.toString.call('Hello')); // 输出: "[object String]"
console.log(Object.prototype.toString.call(42)); // 输出: "[object Number]"
console.log(Object.prototype.toString.call(true)); // 输出: "[object Boolean]"
console.log(Object.prototype.toString.call(undefined)); // 输出: "[object Undefined]"
console.log(Object.prototype.toString.call(null)); // 输出: "[object Null]"
console.log(Object.prototype.toString.call(Symbol('id'))); // 输出: "[object Symbol]"
console.log(Object.prototype.toString.call({})); // 输出: "[object Object]"
console.log(Object.prototype.toString.call([])); // 输出: "[object Array]"
console.log(Object.prototype.toString.call(function() {})); // 输出: "[object Function]"