1.instanceof:
instanceof 是用来检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。例如:
function A() {}
function B() {}
let a = new A()
a instanceof A // true ,因为Object.getPrototypeOf(a) === A.prototype。
a instanceof B // false, 因为B.prototype 不在a的原型链上。
a instanceof Object // true, 因为Object.prototype.isPrototypeOf(a) = true。
但是 instanceof 也存在缺陷,就是它不能精确的判断 Object 类的具体数据类型。例如:
[] instanceof Array; // true, Object.getPrototypeOf([]) === Array.prototype
function A() {};
let a = new A();
a instanceof A ; // true,同上
[] instanceof Object; // true, 这是什么原因呢?
a instanceof Object; // true, 这是什么原因呢?
从上面的例子我们可以发现 [ ] 通过 instanceof 可以判断出其实 Array 的实例对象,但是不能辨别 [ ] 不是 Object 的实例对象,通过构造函数也是这个效果,造成这样的原因:主要与原型链有关:[ ].__proto__ 指向的是 Array.prototype,而 Array.prototype.__proto__ 指向的是 Object.prototype,Object.prototype.__proto__ 指向了 null。同理 a.__proto__ 指向的是Function.prototype,而Function.prototype.__proto__ 指向了 Object.prototype。
2. 原理实现:
function _instanceof(E, C){
let c = C.prototype;
let e = E.__proto__;
while(true){
if(e === null){
return false
}
if(e === c) {
return true
}
e = e.__proto__
}
}
let arr = []
console.log(__instanceof(arr, Array)) // true
总结:综上所述,其实发现instanceof其实就是原型链的一个查找过程。
3.判断类型的通用方法:
function typesof(type) {
let typeList = {};
['Boolean','Number','String','Function','Array','Date','RegExp','Object','Error','Symbol'].forEach((item) => {
typeList[`[object ${item}]`] = item.toLowerCase();
});
if (type == null) {
return type + "";
}
if (typeof type === "object" || typeof type === "function") {
return typeList[toString.call(type)] || "object";
} else {
return typeof type;
}
}
console.log(typesof([])); // 'array'
console.log(typesof(123)); // 'number'
console.log(typesof("123")); // 'string'
console.log(typesof({})); // 'object'
console.log(typesof(true)); // 'boolean'
console.log(typesof(Symbol())); // 'symbol'
console.log(typesof(new Date())); // 'date'
console.log(typesof(new RegExp())); // 'regexp'
console.log(typesof(new Error())); // 'error'
console.log(typesof(function a(){})); // 'function'