深入理解JavaScript-instanceof——找祖籍

87 阅读2分钟

我们分别在 JavaScript由什么组成JavaScript 中的始皇 两篇文章中讲到了 instanceof,这篇文章好好说说 instanceof

什么是 instanceof?

MAN 的解释是:

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

由此可知,instanceof 的左侧必须是对象,才能找到它的原型链

而 instanceof 右侧必须是函数,函数才会有 prototype 属性

简单例子:

function Resume(name, age, hobby) {
    this.name = name;
    this.age = age;
    this.hobby = hobby;
}


const johan = new Resume('johan', '18', 'swim');




console.log(johan instanceof Resume); // true
console.log(johan instanceof Object); // true

console.log(johan instanceof Resume); // true console.log(johan instanceof Object); // true

JavaScript 中的始皇 中有个例子:

Object instanceof Object
Function instanceof Function

我们可以这样理解,Object 的某一原型链上有一值和 Object.prototype 相等;Function 的原型链上的某一值也与 Function.prototye 一致;

Object instanceof Object 可以理解为:

  • Object.proto === Function.prototype
  • Function.prototype.proto === Object.prototype
  • Object.proto.proto === Object.prototype

Function instanceof Function 可以理解为:

  • Function.proto === Function.prototype

其本质是因为内置函数都是由 Function 构造函数创造的,包括它自己

手写 instanceof

按照以上描述,即左边的__proto__=== 右边.prototype

第一版

// 第一版
function myInstanceof(left, right) {
if (left.proto === right.prototype) {
return true;
} else {
return false;
}
}




console.log(myInstanceof(johan, Resume)); // true
console.log(myInstanceof(johan, Object)); // false

console.log(myInstanceof(johan, Resume)); // true console.log(myInstanceof(johan, Object)); // false

第一版我们实现了 左边的__proto__=== 右边.prototype。但这还不够,myInstanceof 还要检测 left 是否在 right 的原型链上。所以我们要递归 left.proto 。直到原型链的最深一层 null

第二版

// 第二版
function myInstanceof(left, right) {
if (left.proto === right.prototype) {
return true;
} else {
if (left === null) {
return false;
}
return myInstanceof(left.proto, right);
}
}

第三版:考虑它是基本类型

在一开始就说了,instanceof 的左侧必须是对象,这样才能找到它的原型链

但不要忘记了,除了 null、undefined 外的基本类型,都是由基本包装类型“保护”着

var num = 1;
console.log(myInstanceof(num, Number)); // true
console.log(num instanceof Number); // false

所以我们要增加对基本类型的判断

function myInstanceof(left, right) {
if (typeof left !== 'object' || left === null) return false;
if (left.proto === right.prototype) {
return true;
} else {
if (left === null || left.proto === null) {
return false;
}
return myInstanceof(left.proto, right);
}
}

看看别人的 instanceof 实现

function myInstanceof(left, right) {
// 基本数据类型直接返回 false
if (typeof left !== 'object' || left === null) return false;
// getPrototype是Object对象自带的一个方法,等效于__proto__
let proto = Object.getPrototypeOf(left);
while (true) {
// 循环往下寻找,知道找到相同的对象
if (proto == null) return false;
// 找到相同的原型对象
if (proto == right.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}

while 的用法比俺高级多了

系列文章