【问题标题】:x is not a function ... what would you expect Object.create to do with a constructorx 不是一个函数......你希望 Object.create 用构造函数做什么
【发布时间】:2013-10-04 18:37:59
【问题描述】:

对于这个问题,我不希望有解决方案来解决问题,但希望更好地理解问题..

规范中的一些引用:

  • 5.1 版 (Link)

    §15.2.3.5 Object.create(O [,属性])

    create 函数创建一个具有指定原型的新对象。调用create函数时,会采取以下步骤:

    1. 如果 Type(O) 不是 Object 或 Null,则抛出 TypeError 异常。
    2. 让 obj 成为创建新对象的结果,就像通过表达式 new Object() 一样,其中 Object 是具有该名称的标准内置构造函数
    3. 将obj的[[Prototype]]内部属性设置为O。
    4. 如果参数 Properties 存在且未定义,则向 obj 添加自己的属性,就像通过使用参数 obj 和 Properties 调用标准内置函数 Object.defineProperties 一样。
    5. 返回对象。
  • 第 6 版 - 草稿 (Link)

    §19.1.3.2 Object.create (O [, Properties])

    create 函数创建一个具有指定原型的新对象。调用create函数时,会采取以下步骤:

    1. 如果 Type(O) 不是 Object 或 Null,则抛出 TypeError 异常。
      1. 令 obj 为带有参数 O 的抽象操作 ObjectCreate 的结果。
      2. 如果参数属性存在且未定义,则 一种。返回抽象操作 ObjectDefineProperties(obj, Properties) 的结果。
      3. 返回对象。

如果我理解正确,这两个规范都允许执行以下代码:

function F() {
}

var x=Object.create(F);

// a minimal test
alert(x.prototype.constructor===F); // true
alert(x instanceof Function) // true
alert(typeof x) // 'object'

似乎它创建了一个类型的对象,该类型派生自 (对不起,糟糕的术语......)Function,正如我在 FireFox 中测试的那样,所以x不可调用的

x(); // x is not a function 

我在想为什么不禁止将构造函数用作O,或者只创建一个有效的构造函数。

所以我想知道您希望 Object.create 对构造函数做什么?

【问题讨论】:

  • 我希望Object.create 忽略它是否是构造函数,因为该算法不需要可调用对象。因为它返回一个简单的Object,我也希望结果是不可调用的。
  • 赏金有什么用?是否还有未解决的问题?您希望答案更详细吗?
  • 当两个投票数相同时,很难选择一个标记为已接受的答案。

标签: javascript


【解决方案1】:

很遗憾,这行不通。你所拥有的是一个在其原型链中有F 的对象; F 是一个函数这一事实并不能使 x 成为一个函数。

只有通过函数声明或函数表达式创建的对象才会有“Function”作为它们的 [[Class]] 和一个 [[Call]] 方法,这使得它可以调用。这些是根据section 13.2 of the ECMAScript 5 specification 上详述的步骤创建的。

Object.create 的算法做了一些不同的事情,正如您在报价中看到的那样。在您的情况下,x 将是具有 [[Class]] "Object" 且没有 [[Call]] 方法的常规对象。如果您尝试Object.prototype.toString.call(x),您将得到"[object Object]",其中“Object”是x 的[[Class]]。 x instanceof Function 只返回true,因为Function 构造函数是x 原型链的一部分(通过F)。

我不确定 ES6 中是否会改变这些,但我想不会。

【讨论】:

  • instanceof 与 [[Class]] 没有任何关系,请更正那句话。
  • 非常正确@Bergi,已修复。
【解决方案2】:

所以我想知道您希望 Object.create 对构造函数做什么?

我当然希望它遵循规范……

我在想为什么它也不允许将构造函数用作 O

为什么要这样做?每个构造函数都是一个object (§8.6)

... 或者只是创建一个有效的构造函数。

规范说它应该创建一个普通对象(如new Object),其 [[prototype]] 设置为 O。普通对象没有函数,它们没有 [[call]] 或 [ [构造]] 属性。它还将有 [[class]] Object,而不是 Function

x.prototype.constructor===F // true
x instanceof Function // true
typeof x // 'object'

似乎它创建了一个类型的对象,该类型派生自(对不起,糟糕的术语..)函数

实际上来自F。它确实从F 继承了.prototype 属性(这就是为什么您的第一个测试是true),并且通过F 它还从Function.prototype 继承,这使它成为instanceof Function。然而,它没有 [[call]] 属性(它不可调用),所以 typeof 不会产生 "function",而只会产生 "object"

【讨论】:

  • 好点。我认为的原因是,因为它是一个工作规范并且经常更改,为什么不决定让它更有用或更严格以避免创建不寻常的对象..
  • 不,Object.create 的定义非常明确,不会改变其严格和简约的行为。 (构造函数)函数的任何“继承”解决方案都将在额外函数中以不同的术语指定,以保持关键的向后兼容性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多