在 JavaScript 开发中,instanceof 操作符是我们经常使用的一个工具,用于检查对象是否属于某个构造函数的实例。但你是否曾想过它的内部工作原理是什么?今天我们将深入探讨 instanceof 的机制,手动实现它,并分析实现过程中需要注意的各种细节。
function Person(name) { this.name = name; } const john = new Person('John'); console.log(john instanceof Person); // true console.log(john instanceof Object); // trueinstanceof 操作符检查对象的原型链中是否存在指定构造函数的 prototype 属性。
function myInstanceof(left, right) { let proto = left.__proto__; let prototype = right.prototype; while(true) { if(proto === null) return false; if(proto === prototype) return true; proto = proto.__proto__; } }这个实现虽然基本正确,但存在几个关键问题:
.处理原始值(非对象)的情况
function myInstanceof(left, right) { // 检查 right 参数是否为函数 if (typeof right !== 'function') { throw new TypeError('Right-hand side of instanceof is not callable'); } // 原始值(非对象和函数)直接返回 false if (left === null || (typeof left !== 'object' && typeof left !== 'function')) { return false; } // 遍历原型链 let proto = Object.getPrototypeOf(left); const prototype = right.prototype; // 堆代码 duidaima.com while (proto !== null) { if (proto === prototype) { return true; } proto = Object.getPrototypeOf(proto); } return false; }实现细节解析
// 错误的用法应该抛出错误 myInstanceof({}, null); // TypeError: Right-hand side of instanceof is not callable myInstanceof({}, {}); // TypeError: Right-hand side of instanceof is not callable这与原生 instanceof 的行为保持一致,提供了更好的错误提示。
// 原始值应该返回 false myInstanceof(42, Number); // false myInstanceof('hello', String); // false myInstanceof(true, Boolean); // false myInstanceof(null, Object); // false myInstanceof(undefined, Object); // false注意:虽然 42 instanceof Number 返回 false,但 new Number(42) instanceof Number 返回 true,因为前者是原始值,后者是对象。
function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype); const myDog = new Dog(); // 原型链:myDog -> Dog.prototype -> Animal.prototype -> Object.prototype -> null console.log(myInstanceof(myDog, Dog)); // true console.log(myInstanceof(myDog, Animal)); // true console.log(myInstanceof(myDog, Object)); // true边界情况测试
// 测试用例 function testCases() { function Person() {} function Animal() {} const person = new Person(); const animal = new Animal(); // 基本功能测试 console.log(myInstanceof(person, Person)); // true console.log(myInstanceof(animal, Animal)); // true console.log(myInstanceof(person, Animal)); // false // 继承关系测试 function Student() {} Student.prototype = Object.create(Person.prototype); const student = new Student(); console.log(myInstanceof(student, Student)); // true console.log(myInstanceof(student, Person)); // true console.log(myInstanceof(student, Object)); // true // 原始值测试 console.log(myInstanceof(42, Number)); // false console.log(myInstanceof('test', String)); // false console.log(myInstanceof(true, Boolean)); // false console.log(myInstanceof(null, Object)); // false console.log(myInstanceof(undefined, Object)); // false // 包装对象测试 console.log(myInstanceof(new Number(42), Number)); // true console.log(myInstanceof(new String('test'), String)); // true // 函数测试 console.log(myInstanceof(() => {}, Function)); // true console.log(myInstanceof(Person, Function)); // true // 数组测试 console.log(myInstanceof([], Array)); // true console.log(myInstanceof([], Object)); // true // 错误情况测试 try { myInstanceof({}, null); } catch (e) { console.log(e instanceof TypeError); // true } try { myInstanceof({}, {}); } catch (e) { console.log(e instanceof TypeError); // true } } testCases();实际应用场景