“new”关键字如何按ECMAScript 5标准中的描述工作

时间:2013-06-29 11:29:28

标签: javascript

我想知道new运算符是如何工作的,而不只是学习如何使用它。我查看了ECMAScript 5 standard并找到算法描述它是如何工作的但是对于吝啬有点困惑它的。

  

生产NewExpression : new NewExpression被评估为   如下:

     
      
  1. ref成为评估NewExpression的结果。
  2.   
  3. constructor为GetValue(ref)。
  4.   
  5. 如果Type(constructor)不是Object,则抛出TypeError例外。
  6.   
  7. 如果constructor未实施[[Construct]]内部方法,则抛出TypeError例外。
  8.   
  9. 返回在[[Construct]]上调用constructor内部方法的结果,不提供任何参数(即参数的空列表)。
  10.   

我尝试使用此示例了解上述算法:

var f = function() {};    
var h = new f();

特别是我不了解第一步,因此无法遵循其他步骤。

  
      
  1. ref成为评估NewExpression的结果。
  2.   
var h = new f();
        ~~~ ~~~~
         |    \_________ NewExpression 
     new operator

这是否意味着reff()的值?但它是undefined

  

3。如果Type(constructor)不是Object,则抛出TypeError例外。

但是f的类型是函数,是否会引发TypeError异常?

  

5。返回在[[Construct]]上调用constructor内部方法的结果,不提供任何参数(即,参数的空列表)。

[[Construct]]函数的内部属性,在constructor上调用它的含义是什么?

2 个答案:

答案 0 :(得分:3)

首先,我们必须澄清new NewExpression,特别是NewExpression是什么。这可以在Annex A中找到。此规则适用的最常见情况是您不将参数传递给构造函数。即

var obj = new F;

其中F指的是一个函数。所以这是允许你省略括号的规则。

在您的示例(var h = new f();)中,您有括号,即您传递的是一个空的参数列表,因此此算法不适用f() NewExpression

相反,此算法适用:new MemberExpression Arguments。它以几乎相同的方式进行评估,并且算法也可以在§11.2.2中找到,就在您引用的算法之后。

考虑到这一点,让我们一步一步地完成该算法:

  

1。让ref成为评估MemberExpression的结果。

在您的示例中,MemberExpressionf,即它是变量。 The result of the evaluation是一个特殊的Reference对象。这里究竟是什么并不重要。只要知道它包含有关如何从变量中实际获取值的信息 所以现在ref指的是那个参考。

  

2。让constructor成为GetValue(ref)

这是实际检索变量的值,constructor将引用f引用的函数。

  

3。让argList成为评估Arguments的结果,生成参数值的内部列表(11.2.4)。

在您的情况下,Arguments(),因此它是一个空列表。

  

4。如果Type(constructor)不是Object,则抛出TypeError例外。

重要的是要知道功能是对象!因此,如果在new表达式中使用了原始值,则此步骤将抛出错误。

  

5。如果constructor未实现[[Construct]]内部方法,则抛出TypeError例外。

所有函数(以及可能的其他对象)实现内部[[Construct]]属性,该属性执行新对象的实际实例化。如果对象没有这样的属性,则不能将其用作构造函数。它的功能如何在§13.2.2中定义。

  

6。返回在构造函数上调用[[Construct]]内部方法的结果,提供列表argList作为参数值。

这是实际施工的结果。 [[Construct]]本身就是函数,在§13.2.2中定义。该方法与每个函数相同,负责创建一个新对象,在该新对象上调用该函数并返回该函数或函数返回的任何函数。

以下是JavaScript(部分伪代码)的外观示例:

[[Construct]] = function(F, argList) {
    // Create new object that in inherits from F.prototype or Object.prototype
    var proto = F.prototype;
    var obj = Object.create(typeof proto === 'object' ? proto : Object.prototype);

    // Call F with this set to obj and pass the argument list
    var result = F.apply(obj, argList);

    // If result is not an object, return the generated object
    return typeof result === 'object' ? result : obj;
};

答案 1 :(得分:2)

让我们一步一步地了解

  1. 解决new window['foo' + 1 + 'bar'] - >等问题。 new window.foo1bar
  2. 确定实际引用的对象:什么是window?全局对象的局部变量或属性?
  3. 这很明显。
  4. 不是那么明显,但重点是:每个Function都是构造函数,但不是每个构造函数都是Function。这一点确保new仅在构造函数上调用。
  5. 运行构造函数。请注意,规范还为案例MemberExpression : new MemberExpression Arguments
  6. 提供了new foo(...)