手写实现 instanceof 运算符
理解 JavaScript 原型链,手动实现 instanceof 运算符的逻辑
问题
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。我们需要手动实现这个运算符的功能,以加深对 JavaScript 原型链机制的理解。
解答
/**
* 手写实现 instanceof 运算符
* @param {Object} obj - 需要检测的实例对象
* @param {Function} constructor - 构造函数
* @returns {Boolean} - 如果 obj 是 constructor 的实例则返回 true,否则返回 false
*/
function myInstanceOf(obj, constructor) {
// 基本类型直接返回 false
if (obj === null || typeof obj !== 'object' && typeof obj !== 'function') {
return false;
}
// 构造函数必须是函数类型
if (typeof constructor !== 'function') {
throw new TypeError('Right-hand side of instanceof is not callable');
}
// 获取构造函数的 prototype
const prototype = constructor.prototype;
// 获取对象的原型
let proto = Object.getPrototypeOf(obj);
// 沿着原型链查找
while (proto !== null) {
// 找到相同的原型,返回 true
if (proto === prototype) {
return true;
}
// 继续向上查找
proto = Object.getPrototypeOf(proto);
}
// 遍历完原型链都没找到,返回 false
return false;
}
使用示例
// 示例 1: 基本使用
function Person(name) {
this.name = name;
}
const person = new Person('张三');
console.log(myInstanceOf(person, Person)); // true
console.log(myInstanceOf(person, Object)); // true
console.log(myInstanceOf(person, Array)); // false
// 示例 2: 数组检测
const arr = [1, 2, 3];
console.log(myInstanceOf(arr, Array)); // true
console.log(myInstanceOf(arr, Object)); // true
// 示例 3: 基本类型
console.log(myInstanceOf(123, Number)); // false
console.log(myInstanceOf('hello', String)); // false
console.log(myInstanceOf(null, Object)); // false
// 示例 4: 包装对象
const num = new Number(123);
console.log(myInstanceOf(num, Number)); // true
console.log(myInstanceOf(num, Object)); // true
// 示例 5: 继承关系
class Animal {}
class Dog extends Animal {}
const dog = new Dog();
console.log(myInstanceOf(dog, Dog)); // true
console.log(myInstanceOf(dog, Animal)); // true
console.log(myInstanceOf(dog, Object)); // true
// 示例 6: 自定义原型链
function Parent() {}
function Child() {}
Child.prototype = new Parent();
const child = new Child();
console.log(myInstanceOf(child, Child)); // true
console.log(myInstanceOf(child, Parent)); // true
关键点
-
原型链遍历:通过
Object.getPrototypeOf()方法不断获取对象的原型,沿着原型链向上查找 -
边界条件处理:
- 基本类型(null、undefined、number、string、boolean)直接返回 false
- 构造函数必须是函数类型,否则抛出类型错误
-
终止条件:
- 找到匹配的 prototype 时返回 true
- 原型链遍历到顶端(null)时返回 false
-
与原生 instanceof 的区别:原生 instanceof 是运算符,性能更优;手写版本主要用于理解原型链机制
-
原理:instanceof 的本质是检查
constructor.prototype是否在obj的原型链上,这体现了 JavaScript 基于原型的继承机制
目录