1

我想知道new运算符是如何工作的,而不仅仅是学习如何使用它。我查看了ECMAScript 5 标准,发现算法描述了它是如何工作的,但对它的含义有点困惑。

生产NewExpression : new NewExpression评估如下:

  1. ref是评估 NewExpression 的结果。
  2. 设为GetValue constructor(ref)。
  3. 如果Type(constructor)不是Object,则抛出TypeError异常。
  4. 如果constructor没有实现[[Construct]]内部方法,则抛出TypeError异常。
  5. 返回调用[[Construct]]on 内部方法的结果constructor,不提供任何参数(即一个空的参数列表)。

我尝试使用这个例子来理解上面的算法:

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

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

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

这是否意味着ref的价值f()?但它是undefined

3. 如果Type(constructor)不是Object,则抛出TypeError异常。

但是f是函数的类型,会不会抛出TypeError异常呢?

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

[[Construct]]函数的内部属性,调用它是什么意思constructor

4

2 回答 2

3

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

var obj = new F;

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

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

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

考虑到这一点,让我们逐步了解该算法:

1. 让ref是评估的结果MemberExpression

在您的示例中,MemberExpression, is f,即它是一个变量。评估的结果是一个特殊的Reference对象。它到底是什么并不重要。只要知道它包含有关如何从变量中实际获取值的信息。
所以现在ref指的是那个参考。

2.constructorGetValue(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;
};
于 2013-07-04T11:34:42.183 回答
2

让我们一步一步来

  1. 解决诸如new window['foo' + 1 + 'bar']->new window.foo1bar
  2. 确定实际引用的对象:什么是window?全局对象的局部变量或属性?
  3. 这是显而易见的。
  4. 不是很明显,但重点是:everyFunction是构造函数,但不是每个构造函数都是Function. 这一点确保new仅在构造函数上调用。
  5. 运行构造函数。请注意,规范还提供MemberExpression : new MemberExpression Arguments了案例new foo(...)
于 2013-06-29T12:24:22.150 回答