JavaScript instanceof 原理与手写实现详解

作者:小括号时间:2026-10-25 22:31:02浏览:215

本文深入解析 JavaScript 中 instanceof 运算符的工作原理,即检测构造函数 prototype 是否位于实例对象的原型链上。通过对比基本类型与包装对象的区别,阐明常见误区,并提供基于 __proto__ 循环查找的手写实现代码,帮助开发者深入理解原型继承机制。

方法介绍

instanceof 运算符解析

该运算符的核心功能是检测构造函数的 prototype 属性是否存在于指定实例对象的原型链中。

基本语法结构为:object instanceof constructor。其中 object 代表待检测的实例对象,constructor 代表目标构造函数。

简而言之,instanceof 用于判断 constructor.prototype 是否位于参数 object 的原型链之上。

个人理解:

instanceof 用于判定左侧对象是否为右侧构造函数的实例。具体而言,它检查左侧对象能否通过其隐式原型 在原型链中逐层向上查找,直至找到右侧函数的原型对象。若函数原型对象出现在实例对象的原型链上,则返回 true。

通俗理解:判断右侧构造函数是否为左侧对象的父级、祖父级或更高层级的祖先。只要左侧对象继承自右侧函数,结果即为 true。

instanceof 使用规范

调用格式为 object instanceof 构造函数。此操作包含两个必需参数:左侧参数必须为对象类型,右侧参数必须为函数类型。最终返回值为 Boolean 类型。

注意事项:常有人误以为 JavaScript 中万物皆对象,从而尝试 'str' instanceof String 这类写法,结果返回 false。原因在于 'str' 仅为基本字符串类型,而通过 String 构造函数(如 new String('str'))创建的是字符串包装对象。两者存在本质区别,可在控制台查看差异。同理,new Number(3) instanceof Number 或 new Boolean(true) instanceof Boolean 等包装对象检测会返回 true。

代码示例:

// 定义构造函数
function C () {}
function D () {}
// 实例化一个 o 对象
var o = new C()
// true,true --> C.prototype 在 o 的原型链上
console.log(o instanceof C, o.__proto__ === C.prototype, '此时 o 的 __proto__:', 
o.__proto__, '此时 C 的 prototype:', C.prototype)
// false,false --> D.prototype 不在 o 的原型链上
console.log(o instanceof D, o.__proto__ === D.prototype)
// true true --> Object.prototype 在 o 的原型链上
console.log(o instanceof Object, o.__proto__.__proto__ === Object.prototype)
// 这时我们修改构造函数 C 的原型为一个空对象
C.prototype = {}
// 实例化一个 o2 对象
var o2 = new C()
// true --> C.prototype 在 o2 的原型链上
console.log(o2 instanceof C)
// false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
console.log(o instanceof C, '此时 o 的 __proto__:', o.__proto__, '此时 C 的 prototype:', C.prototype)
console.log('此时 D 的 prototype:', D.prototype);
// 继承
D.prototype = new C()
console.log('此时 D 的 prototype:', D.prototype);
var o3 = new D()
// true, true --> 因为 o3 是 构造函数 D new 出来的实例对象,所以 D.prototype 一定在 o3 的原型链上
console.log(o3 instanceof D, o3.__proto__ === D.prototype)
// true --> 因为 C.prototype 现在在 o3 的原型链上
console.log(o3 instanceof C)
// true,true --> 上面的结果为什么为 true 呢,看如下代码,D.prototype 是 构造函数 C new 出来的实例对象,所以 C.prototype 一定在 D.prototype 的原型链上
console.log(o3.__proto__ === D.prototype, D.prototype.__proto__ === C.prototype);
// true 相当于如下代码
console.log(o3.__proto__.__proto__ === C.prototype);

手动实现思路

基于前述原理,instanceof 的判断逻辑是:利用左侧对象的隐式原型属性 沿原型链逐层向上查找,若找到右侧构造函数的 prototype 属性,则返回 true。明确此机制后,即可编写自定义的 instanceof 函数。

注:实现过程需借助循环结构。

function myInstanceof(obj, func) {
    if(!['function', 'object'].includes(typeof obj) || obj === null) {
    	// 基本数据类型直接返回false,因为不满足instanceof的左侧参数是对象或者说引用类型
        return false
    }
    let objProto = obj.__proto__, funcProto = func.prototype
    while(objProto !== funcProto) {
    	// obj.__proto__不等于func.prototype时,继续通过__proto__向上层查找
    	// 当找到原型链尽头Object.prototype.__proto__=null 时还未找到,就返回false
        objProto = objProto.__proto__
        if(objProto === null){
            return false
        }
    }
    // obj.__proto__ 等于 prototype = func.prototype 时,不会进入上面循环,返回true
    // 不等进入上面循环,找到相等时会跳出循环,走到这里返回true
    return true
}
//测试
function A(){}
let a=new A;
console.log(myInstanceof(a,A))//true
console.log(myInstanceof([],A))//false

以上为 JavaScript instanceof 方法原理及手写实现的详细解析,更多相关技术资料请参阅本站其他文章。

作者最新文章