【问题标题】:isPrototypeOf says no, but instanceof says yes – what's going on?isPrototypeOf 说不,但 instanceof 说是——这是怎么回事?
【发布时间】:2015-03-30 23:34:37
【问题描述】:

我尝试对错误进行一些简单的类型检查,并得到以下代码:

function isError(x) {
  return Error.isPrototypeOf(x)
}

但是,如果我调用带有错误实例的函数,我会得到false,如下所示:

isError(new RangeError) // false

所以我启动了节点(好吧,无论如何,io.js),并做了以下事情:

> Object.getPrototypeOf(Object.getPrototypeOf(new RangeError))
[Error]

最后,如果我使用instanceof 进行检查,它可以正常工作,如下所示:

> (new RangeError) instanceof Error
true

那么,这里到底发生了什么?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    instanceof 为您查看指定构造函数的.prototype 属性(即不是[[Prototype]]/__proto__)(即它做了一些额外的工作)。

    isPrototypeOf 工作不那么辛苦,需要您指定要在原型链上检查的确切对象实例。

    Error.isPrototypeOf(r = new RangeError); // false.
    

    false 因为函数Error 不在r 的原型链上。 r的原型链为:

    r => RangeError.prototypeError实例)=> Error.prototypeObject实例

    这条链上没有Error构造函数,因此是错误的。

    如果我们像这样修改您的示例:

    Error.prototype.isPrototypeOf(r = new RangeError); // true.
    

    这会返回 true,因为 Error 函数的 .prototype 属性r 的原型链上。

    【讨论】:

    • RangeError.prototype 真的是Error 的一个实例吗?
    • @KubaWyrostek 是的,我相信是的。如果你知道得更好,请告诉我。
    • 我不知道更好。我只是问。 :-) 是不是RangeError.prototype = Object.create(Error.prototype) 而不是RangeError.prototype = new Error()
    • 好的,我没有考虑过这种细微的区别。甚至有可能找出答案吗?您要强调的是与实现相关的区别。
    • 我猜不可能。这实际上取决于我们如何定义“实例”。别介意我的问题,我只是想把一些事情弄清楚。 :-)
    【解决方案2】:

    isPrototypeOfgetPrototypeOf 直接查看原型链,而instanceof 查看给定构造函数的.prototype 属性。你需要使用:

    function isError(x) {
      return Error.prototype.isPrototypeOf(x)
    }
    

    您的函数测试x 是否继承自Error 构造函数函数对象

    【讨论】:

    • 但是使用instanceof更容易?
    • 这很有道理,谢谢。这导致我尝试其他方法:Object.getPrototypeOf(Error).isPrototypeOf(new RangeError) 返回 false,而 Error.prototype.isPrototypeOf(new RangeError) 返回 true – 这是怎么回事?
    • Object.getPrototypeOf(new Error()).isPrototypeOf(new RangeError)返回true,你要明白构造函数的prototype属性和实例的prototype的区别,一般是__proto__
    • 也就是说,Object.getPrototypeOf(Error)Function.prototype,因为你要的是函数的原型(构造函数)
    • 当然,这是有道理的。我认为今天的咖啡不够(或太多!)非常感谢您的洞察力!
    猜你喜欢
    • 2018-11-21
    • 2013-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2011-04-26
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多