算法 - 手写 instanceof
1. 题目
实现一个函数 myInstanceof(left, right),等价于原生 instanceof 运算符:
- 判断
left是否是right的实例,即right.prototype是否出现在left的原型链上。 - 是返回
true,否则返回false。
示例:
1 | myInstanceof([], Array) // true |
2. 解题思路
instanceof 的本质:沿 left 的原型链逐级向上查找,看能否碰到 right.prototype。
关键概念澄清:
instanceof判断的不是「谁 new 出来的」,而是「left.__proto__链上有没有right.prototype这个对象引用」。- 原型链靠
__proto__(即Object.getPrototypeOf)向上走;构造函数的prototype挂在实例的__proto__上。
算法步骤:
- 若
left是原始值或null,直接false(原始值没有原型链,原生也会返回 false)。 - 取
right.prototype作为目标。 - 从
Object.getPrototypeOf(left)开始,沿__proto__上溯:命中目标即true;到null(原型链顶)仍未命中则false。
进阶:原生
instanceof会先调用right上的静态方法Symbol.hasInstance(若定义),能提到这点是满分细节。
- 时间复杂度:
O(原型链长度)。
3. TypeScript 实现
1 | function myInstanceof(left: any, right: any): boolean { |
4. 面试延伸
- 原型链三条铁律要能脱口而出:
实例.__proto__ === 构造函数.prototype;构造函数.__proto__ === Function.prototype;Object.prototype.__proto__ === null(链顶)。 instanceofvstypeofvsObject.prototype.toString:typeof只分原始类型、instanceof查原型链判引用类型、toString.call(x)最精确(能区分 Array/Date/RegExp)。三者的适用边界是高频追问。- 跨 realm 失效:
iframe里的数组用instanceof Array会 false(不同全局的Array.prototype不同),此时应改用Array.isArray。能点出这个坑非常加分。 class语法糖:extends建立的正是一条Dog.prototype.__proto__ === Animal.prototype的链,instanceof才因而能向上命中父类。Function instanceof Function === true、Object instanceof Function === true这些「鸡生蛋」常用来考你原型图是否清晰。
难度:中等 | 手写题 | 原型链理解试金石