一、JS辨别一个对象类型的方法
在JavaScript中,检测一个变量的类型,有以下三种方法
- typeof操作符:返回一个字符串,表示变量的数据类型
console.log(typeof null) // 输出 "object"
let x;
console.log(typeof x) // 输出 "undefined"
let y = 42;
console.log(typeof y); // 输出 "number"
let arr = [];
console.log(typeof arr); // 输出 "object"
let func = function() {};
console.log(typeof func); // 输出 "function"
- instanceof操作符
- Object.prototype.toString
二、原理
-
instanceof的作用:检测
对象a
是否属于某个类b
的实例对象a instanceof b // 返回true或者false
-
instanceof运算符的原理:检测构造函数的 prototype 属性是否出现在对象的原型链上
- 每个对象都有隐式原型属性
__proto__
,指向该对象的原型对象
(通常使用Object.getPrototypeOf(a)
来获取原型对象,而不会直接访问对象的内部属性__proto__
)- 构造函数的显示原型属性
prototype
,指向构造函数的原型对象- 因此,如果实例a是类b的实例对象,那么a的原型链上必然有b的原型对象
如果a instanceof B
,那么 a 必须是个对象,而 B 必须是一个合法的函数。在这两个条件都满足的情况下:判断 函数B 的 prototype 属性指向的原型对象( B.prototype )是否在对象 a 的原型链上。如果在,则返回true;如果不在,则返回false。简而言之, instanceof 的原理其实就是一个查找原型链的过程。
三、模拟实现instanceof
function myInstanceof(obj, fn){
// 需要判断的构造函数不能是基本数据类型
// if (typeof constructor !== 'function') {
// throw new Error('Right-hand side of instanceof is not callable');
// }
// 获取构造函数的显示原型属性
let fnProto = fn.prototype;
// 获取对象的隐式原型属性
let objProto = Object.getPrototypeOf(obj);
// 判断fnProto是否出现在对象的原型链上
// (因为对象原型链的尽头是null,用它作为跳出while的条件)
while(objProto !== null){
if(objProto === fnProto){
return true;
}
// 获取obj原型对象的原型对象(沿着对象的原型链找,直至指向null)
objProto = Object.getPrototypeOf(objProto);
}
// 当objProto == null时,还找不到
return false;
}