3

注意下面的闭包示例:

<script>
  function foo() {
    var x = 1;
    function bar() {
      var y = 2;
      alert(x + y);
    }
    return bar;
  }

   var dummy = foo(); // Assign variable binding "dummy" to a reference of the "bar" function.
   dummy(); // When entering the "bar" function code, will it go through the execution context creation phase?
</script>

调用虚拟变量绑定(将执行“bar”函数代码)时,是否创建了新的执行上下文?ECMAScript 规范指定了输入函数代码时会发生什么,但由于这是对函数/闭包的引用,我不确定它是否必须再次经历整个执行上下文创建/绑定阶段。

4

2 回答 2

2

好问题。让我们看看发生了什么:

dummy()函数调用 (11.2.3)

参见步骤 #8 “返回调用 func 的 [[Call]] 内部方法的结果,提供 thisValue 作为 this 值并提供列表 argList 作为参数值。”

所以dummy.[[Call]]被调用。转到13.2.1 ( [[Call]])。

令 funcCtx 为使用 F 的 [[FormalParameters]] 内部属性的值、传递的参数 List args 和 10.4.3 中所述的 this 值为函数代码建立新执行上下文的结果。

事实上dummy(),如10.4.3中所述,创建新的执行上下文也是如此。

现在dummy执行了函数代码,按照 10.4.3 中的步骤 #5 创建 NewDeclarativeEnvironmentdummy.[[Scope]]

dummy只是一个参考bar,所以dummy.[[Scope]]bar.[[Scope]]。并bar.[[Scope]]在执行时定义(前一行),自然会为(包括)foo内的每个函数声明创建函数。bar

bar.[[Scope]]本质上是一个由[global environment][foo VE](变量环境)组成的链。所以在执行的那一刻,它会创建自己的 VE,并使用 foo 的 VE 作为外部。范围链现在由[global environment]->[foo VE]->[bar VE].

x在 var 的 VEy中找到,在 bar 的 VE 中找到,并且 alert 成功3作为参数接收 :)

但要回答你原来的问题,是的“输入功能代码”发生在

(function(){ ... })();

如果是

f();

因为它们本质上都是调用函数的 [[Call]]。只是第一个是CallExpression由 组成的FunctionExpressionArguments而第二个是CallExpression由 组成IdentifierArguments

两者仍然解析为一个函数对象,该对象具有内部 [[Call]] 方法,这是被执行的。

于 2013-03-01T04:07:33.520 回答
0

我认为范围链是您在这里寻找的东西:

来自http://www.amazon.com/JavaScript-Definitive-Guide-Activate-Guides/dp/0596805527/ref=sr_1_2?ie=UTF8&qid=1362066219&sr=8-2&keywords=javascript (3.10.3)

每次调用函数时,它都会创建一个新对象来存储其局部变量,并将该新对象添加到存储的作用域链中,以创建一个新的更长的链来表示该函数调用的作用域。

对于您的问题,是的,它将再次遍历整个执行上下文,否则您如何从 bar() 返回另一个函数,例如

function bar() {
      var y = 2;
      alert(x + y);

return function() {alert('hello');}
    }
于 2013-02-28T15:46:53.097 回答