-
typeof [value]:检测的结果是一个字符串,字符串中包含了对应的数据类型
- 缺点:
- typeof null => “object”
- typeof不能细分对象(除函数)
- 优点:typeof检测速度快,性能好
- 底层原理:
- 所有数据类型值,在计算机底层都是按照“64位,2进制”来存储的,所有对象数据类型值,前三位都是“0”,而存储null的二进制代码全是0
- typeof就是按照二进制值来进行检测的(性能好),例如:它认为前三位是0的就是对象,在这基础上再看对象是否实现了call方法,如果实现了结果就是“function”,没有实现,结果就是“object”,所有它也不能细分对象
- 缺点:
-
instanceof:检测某个实例是否属于这个类
-
作用:弥补typeof的不足,可以把对象类型进行细分
-
问题:结果不一定准确
-
原理:基于instanceof检测的时候,value instanceof Ctor
-
先看Ctor(构造函数)是否存在[Symbol.hasInstance]这个属性方法,如果存在,则基于这个方法进行检测,
Ctor[Symbol.hasInstance](value)
-
如果没有这个属性方法,获取value的原型链(直到找到Object.prototype为止),如果Ctor.prototype出现在它的原型链上,则证明value是Ctor的实例,反之则不是…
-
在新版本浏览器中,在Function.prototype上存在一个属性方法 Symbol.hasInstance,所以只要是函数「不论是普通函数,还是构造函数」,都具备 Symbol.hasInstance 这个方法…
-
可以基于构造函数静态方法重写[Symbol.hasInstance]方法
class Fn { static[Symbol.hasInstance](val) { return false; } } let f = new Fn; console.log(f instanceof Fn); //false console.log(Fn[Symbol.hasInstance](f));
-
-
重写instanceof方法
const instance_of = function instance_of(obj, ctor) { // 格式检验 if (typeof ctor !== "function") throw new TypeError('Right-hand side of instanceof is not callable'); if (!ctor.prototype) throw new TypeError('Function has non-object prototype in instanceof check'); if (obj === null || !/^(object|function)$/i.test(typeof obj)) return false; // 支持Symbol.hasInstance的直接使用这个方法 let hasInstance = typeof Symbol !== "undefined" && ctor[Symbol.hasInstance]; if (hasInstance) { return hasInstance.call(ctor, obj); //ctor[Symbol.hasInstance](obj) } // 不支持的,我们需要自己按照原型链进行查找 let proto = Object.getPrototypeOf(obj); while (proto) { if (proto === ctor.prototype) return true; proto = Object.getPrototypeOf(proto); } return false;
-
};
```
-
constructor:获取实例的构造函数
- 写法:n.constructor === Array/RegExp/Object…
- 缺点:答案不准确
- 优点:可以检测一个对象是否为标准普通对象「纯粹对象」 是Object的直属实例 (实例.proto===Object.prototype)
- 内部操作:(1).constructor -> 把原始值的1默认变为对象类型的实例 new Number(1) “装箱:把原始值默认转换为其构造函数创造的对象类型实例,这样就可以调用所属类原型上的方法了”
-
object.prototype.toString.call([value])
- 大部分类的原型上都有toString方法,都是用来转换为字符串的…但是Object.prototype.toString不是用来转换为字符串的,而是检测数据类型的…
- 这个方法忒好用了…除了写起来麻烦一些,几乎没有漏洞
- 返回结果 “[object ?]”
- 写法:Object.prototype.toString.call([value]);
- Object.prototype.toString.call([value])的底层原理
- 先检查[value][Symbol.toStringTag]属性,如果有这个属性,属性值是啥 @X,最后检测的结果就是 “[object @X]”
- 如果没这个属性,则按照自己所属的内置类进行处理…