一、写在前面
面试高频、代码高频,却依旧让前端同学心里打鼓的三连问:
"typeof 不够吗?"
"instanceof 到底靠不靠谱?"
"手动修改 prototype 会怎样?"
今天,咱们把 instanceof 拉进实验室,做一次彻底的"DNA 检测"。
二、语法速写
javascript
object instanceof Constructor // 返回布尔值
左边:待检测的"孩子"
右边:疑似"父母"的构造函数
一句话:孩子是不是这家生的?
三、核心原理:原型链"家谱"查找
- 取孩子的隐式原型:
Object.getPrototypeOf(obj) - 取父母的"出生证明":
Constructor.prototype - 一级一级往上翻家谱,直到:
- 找到相同的祖先 → 返回
true - 翻到
null还没找到 → 返回false
- 找到相同的祖先 → 返回
伪代码还原引擎逻辑:
javascript
function instanceOf(obj, Ctor) {
if (typeof obj !== 'object' || obj === null) return false;
let proto = Object.getPrototypeOf(obj);
while (proto) {
if (proto === Ctor.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
}
四、三张图看懂全过程
(文本版)
javascript
obj ──proto──> Dog.prototype ──proto──> Animal.prototype ──proto──> Object.prototype ──null
| 检测表达式 | 结果 | 原因说明 |
|---|---|---|
d instanceof Dog |
true | 第一层就匹配 |
d instanceof Animal |
true | 第二层匹配 |
d instanceof Object |
true | 最终层匹配 |
d instanceof Cat |
false | 整个链都没出现 Cat.prototype |
五、四个容易翻车的场景
-
原始值一律 false
"abc" instanceof String // false(包装类
new String('abc')才行) -
跨 iframe 失效
窗口 A 的
[]与窗口 B 的Array不是同一份Array.prototype -
手动篡改 prototype
javascriptfunction F() {} const o = new F(); F.prototype = {}; // 出生证明被撕了 console.log(o instanceof F); // false -
Symbol.hasInstance ------ 黑科技拦截
javascriptclass MyArray { static [Symbol.hasInstance](obj) { return Array.isArray(obj) && obj.length > 3; } } [1,2,3,4] instanceof MyArray; // true [1,2] instanceof MyArray; // false从 ES6 起,引擎优先调用静态方法
Symbol.hasInstance,把"家谱查找"变成"自定义卷子"。
六、instanceof vs typeof 速查表
| 场景 | typeof 结果 | instanceof 结果 | 备注 |
|---|---|---|---|
[] |
'object' | Array | typeof 只能区分数组对象 |
{} |
'object' | Object | 无法区分数组与普通对象 |
new String('') |
'object' | String | 包装类 |
function fn(){} |
'function' | Function | typeof 唯一能识函数 |
null |
'object' | 任意都 false | 历史 Bug |
七、实战:写一个"安全数组"检测器
javascript
const isArray = value => Array.isArray(value) || value instanceof Array;
// 二者等价,但 Array.isArray 更快且跨 iframe 安全
八、小结口诀
"instanceof 不看户口,只看家谱;
家谱可改,Symbol 能挡;
原始值直接拜拜,跨窗面试常踩坑。"
九、延伸思考
- 能否用
Object.create(null)骗过所有instanceof? - 如何给自定义类实现"多重身份"?(提示:mixin + Symbol.hasInstance)
(把本文所有代码片段跑一遍,面试手写不怕卡壳。)
如果这篇"家谱探秘"帮你理清思路,点个 ⭐ 吧!
评论区告诉我:你在哪个场景被 instanceof 坑过?