8000 原型与原型链 - instanceof的底层实现原理及手动实现 · Issue #18 · logan70/Blog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

原型与原型链 - instanceof的底层实现原理及手动实现 #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
logan70 opened this issue Nov 20, 2019 · 2 comments
Open

Comments

@logan70
Copy link
Owner
logan70 commented Nov 20, 2019

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 )

  1. If Type(target) is not Object, throw a TypeError exception.
  2. Let instOfHandler be ? GetMethod(target, @@hasInstance).
  3. If instOfHandler is not undefined, then
  4. Return ToBoolean(? Call(instOfHandler, target, « V »)).
  5. If IsCallable(target) is false, throw a TypeError exception.
  6. Return ? OrdinaryHasInstance(target, V).

OrdinaryHasInstance ( C, O )

  1. If IsCallable(C) is false, return false.
  2. If C has a [[BoundTargetFunction]] internal slot, then
    • Let BC be C.[[BoundTargetFunction]].
    • Return ? InstanceofOperator(O, BC).
  3. If Type(O) is not Object, return false.
  4. Let P be ? Get(C, "prototype").
  5. If Type(P) is not Object, throw a TypeError exception.
  6. Repeat,
    • Set O to ? O.[[GetPrototypeOf]]().
    • If O is null, return false.
    • If SameValue(P, O) is true, return true.
@ZhaoTim
Copy link
ZhaoTim commented Aug 8, 2022

写得太仔细了,背不下来,面试时候感觉只能写个最简单的版本

@logan70
Copy link
Owner Author
logan70 commented Aug 29, 2022

写得太仔细了,背不下来,面试时候感觉只能写个最简单的版本

不用背,前面的都是边界情况处理,或者新标准的兼容,核心还是最后一块儿代码,理解最后一块儿代码,并且面试的时候能说出来我感觉足够了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants
0