是否无法在JavaScript

时间:2015-10-07 17:01:55

标签: javascript

我认真审核ECMAScript 5.1规范。

我很好奇是否有办法告诉"真正的构造函数" ES5中的对象(不是明确的"构造函数"属性)

根据规范,明确"构造函数" property只是从函数对象的 byproduct 对象到函数对象的初始反向引用。

(此处,副产品是最初由功能对象显式"原型"属性指向的对象。)

所以,明确"构造函数" property与对象的真实构造函数无关:

function Foo(name){ this.name = name; }
var foo = new Foo("Brian");
var bar = { a: 10, b: function(){ if(this.name) return this.name; }};
Foo.prototype = bar;
var foo2 = new Foo("John");   // Let me call Foo as "real constructor" of foo2

这里,即使foo2是由Foo创建的,因为Foo.prototype在创建foo2时指向bar,所以foo2的内部[[Prototype]]指向bar,我们可以通过以下方式检查:

Object.getPrototypeOf(foo2) === bar   // true

因为foo2没有自己的"构造函数"像往常一样属性,所以,阅读foo2.constructor实际上是[[Prototype]]链查找,即foo2.constructor - > ((foo2。[[Prototype]]))。构造函数 - > bar.constructor是Object,而不是Foo。

您可以通过以下方式查看:

foo2.constructor === Foo         // false
foo2.constructor === Object      // true

最后,有没有办法从对象foo2中找到Foo?

ADD: 我在谈论ES5。请不要带任何依赖引擎或ES6的东西(例如__proto__

1 个答案:

答案 0 :(得分:4)

不,该语言本身并不提供任何功能。

如果我们咨询spec on the new operator,我们会发现它主要是调用函数的[[Construct]]内部方法。将注意力转向[[Construct]],我们看到:

  

当使用可能为空的参数列表调用Function对象 F 的[[Construct]]内部方法时,将执行以下步骤:

     
      
  1. obj 成为新创建的本机ECMAScript对象。
  2.   
  3. 按照8.12中的规定设置 obj 的所有内部方法。
  4.   
  5. obj 的[[Class]]内部属性设置为" Object"。
  6.   
  7. 将obj的[[Extensible]]内部属性设置为true
  8.   
  9. proto 成为使用参数" prototype"调用F的[[Get]]内部属性的值。
  10.   
  11. 如果Type( proto )是Object,请将 obj 的[[Prototype]]内部属性设置为 proto
  12.   
  13. 如果Type( proto )不是Object,则将 obj 的[[Prototype]]内部属性设置为标准内置Object原型对象,如15.2中所述0.4。
  14.   
  15. 结果成为调用 F 的[[Call]]内部属性的结果,提供obj作为此值并提供传递给[[[]的参数列表构造]] as args。
  16.   
  17. 如果Type( result )是Object,则返回结果。
  18.   
  19. 返回 obj
  20.   

正如您在步骤5到7中所看到的,环境new创建的对象的唯一处理方式是设置其[[Prototype]],然后将其移交给函数'步骤8中处理的[[Call]]方法。如果分配给对象[[Prtototype]]的值不包含准确的constructor属性,则无法知道构造函数是什么创造了一个对象。

当然,您可以通过在创建时在对象上设置值来将该信息存储在自己的构造函数代码中,但JavaScript引擎不会为您执行此操作。