Blog
Blog copied to clipboard
原型与原型链 - instanceof的底层实现原理及手动实现
instanceof的底层实现原理及手动实现
作用
instanceof 用于检测右侧构造函数的原型是否存在于左侧对象的原型链上。
Symbol.hasInstance
ES6新增的内置Symbol,用作对象方法标识符,该方法用于检测任意对象是否为拥有该方法对象的实例。instanceof操作符优先使用该Symbol对应的属性。
这样一来instanceof右侧并非必须为函数,对象也可以的。示例代码如下:
const MyArray = {
[Symbol.hasInstance](obj) {
return Array.isArray(obj)
}
}
expect([] instanceof MyArray).toBe(true)
手写实现
const isObj = obj => ((typeof obj === 'object') || (typeof obj === 'function')) && obj !== null
function myInstanceOf(instance, Ctor) {
if (!isObj(Ctor)) // 右侧必须为对象
throw new TypeError('Right-hand side of 'instanceof' is not an object')
const instOfHandler = Ctor[Symbol.hasInstance]
// 右侧有[Symbol.hasInstance]方法,则返回其执行结果
if (typeof instOfHandler === 'function') return instOfHandler(instance)
// 右侧无[Symbol.hasInstance]方法且不是函数的,返回false
if (typeof Ctor !== 'function') return false
// 左侧实例不是对象类型,返回false
if (!isObj(instance)) return false
// 右侧函数必须有原型
const rightP = Ctor.prototype
if (!isObj(rightP))
throw new TypeError(`Function has non-object prototype '${String(rightP)}' in instanceof check`)
// 在实例原型连上查找是否有Ctor原型,有则返回true
// 知道找到原型链顶级还没有,则返回false
while (instance !== null) {
instance = Object.getPrototypeOf(instance)
if (instance === null) return false
if (instance === rightP) return true
}
}
ECMAScript定义
标准出处 -> ECMAScript#instanceof
InstanceofOperator ( V, target )
- If Type(target) is not Object, throw a TypeError exception.
- Let instOfHandler be ? GetMethod(target, @@hasInstance).
- If instOfHandler is not undefined, then
- Return ToBoolean(? Call(instOfHandler, target, « V »)).
- If IsCallable(target) is false, throw a TypeError exception.
- Return ? OrdinaryHasInstance(target, V).
OrdinaryHasInstance ( C, O )
- If IsCallable(C) is false, return false.
- If C has a [[BoundTargetFunction]] internal slot, then
- Let BC be C.[[BoundTargetFunction]].
- Return ? InstanceofOperator(O, BC).
- If Type(O) is not Object, return false.
- Let P be ? Get(C, "prototype").
- If Type(P) is not Object, throw a TypeError exception.
- Repeat,
- Set O to ? O.[[GetPrototypeOf]]().
- If O is null, return false.
- If SameValue(P, O) is true, return true.
写得太仔细了,背不下来,面试时候感觉只能写个最简单的版本
写得太仔细了,背不下来,面试时候感觉只能写个最简单的版本
不用背,前面的都是边界情况处理,或者新标准的兼容,核心还是最后一块儿代码,理解最后一块儿代码,并且面试的时候能说出来我感觉足够了。