闽公网安备 35020302035485号
在 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); // true
instanceof 操作符检查对象的原型链中是否存在指定构造函数的 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();
实际应用场景