关于javascript:x不是函数…您希望Object.create与构造函数一起做什么

x is not a function … what would you expect Object.create to do with a constructor

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

规范中的一些引述:

  • 版本5.1(链接)

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

    The create function creates a new object with a specified prototype. When the create function is called, the following steps are taken:

  • If Type(O) is not Object or Null throw a TypeError exception.
  • Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name
  • Set the [[Prototype]] internal property of obj to O.
  • If the argument Properties is present and not undefined, add own properties to obj as if by calling the standard built-in function Object.defineProperties with arguments obj and Properties.
  • Return obj.
  • 第6版-草稿(链接)

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

    The create function creates a new object with a specified prototype. When the create function is called, the following steps are taken:

  • If Type(O) is not Object or Null throw a TypeError exception.

  • Let obj be the result of the abstract operation ObjectCreate with argument O.
  • If the argument Properties is present and not undefined, then
    a. Return the result of the abstract operation ObjectDefineProperties(obj, Properties).
  • Return obj.

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

1
2
3
4
5
6
7
8
9
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'

就像我在FireFox中测试的那样,它似乎创建了某种类型的对象(对不起的术语..)Function,因此x是不可调用的:

1
x(); // x is not a function

我在考虑为什么不禁止将构造函数用作O或仅创建有效的构造函数。

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


不幸的是,这行不通。您所拥有的是在其原型链中包含F的对象; F是一个函数的事实并不会使x是一个函数。

仅通过函数声明或函数表达式创建的对象将以" Function"作为其[[Class]],并具有一个[[Call]]方法,这使它可以被调用。它们是根据ECMAScript 5规范的13.2节中详述的步骤创建的。

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

我不确定在ES6中是否会更改其中任何一个,但我想不会。


So I'm wondering what would you expect Object.create to do with a constructor?

我希望它会遵循规范……

I'm thinking about why doesn't it either disallow a constructor to be used as O

为什么要这样每个构造函数都是一个对象(第8.6节)。

… or just create a valid constructor.

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

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

Seems it created an object of a type derives from (sorry for the poor terminology .. ) Function

实际上是从F开始。它确实从F继承了.prototype属性(这就是为什么您的第一个测试是true的原因),并且通过F它??也继承了从Function.prototype使其成为instanceof Function的属性。但是,它没有[[call]]属性(不可调用),因此typeof不会产生"function",而只会产生"object"