创建父词汇环境时

时间:2018-10-23 23:15:08

标签: javascript closures

我一直试图理解在js中创建词法环境的时间。据我所知,词汇环境是在创建阶段和执行阶段两个阶段创建的,但请看下一个简单的闭包。

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);

所以,当makeAdder返回函数时,它返回的函数带有指向x的父词法环境,但是我不明白的是为什么add5已经有一个父词法环境,而返回的内部函数甚至没有已经执行了,所以我可以推断的是,一旦遇到函数定义(返回函数),便附加了父词法环境,这是正确的吗?父词法环境是在代码中声明并到达函数时创建的,而不是在执行时创建的?以及返回的函数的词法环境如何,在执行add5函数时会创建其词法环境。请原谅我只想澄清何时创建父级和本地词法环境的长文本。

先谢谢大家。

1 个答案:

答案 0 :(得分:1)

  

所以我可以推断的是,一旦遇到函数定义(返回函数),便附加了父词法环境,这是正确的吗?

是的,附加到新创建的功能对象上。

  

父词汇环境是在代码中声明并到达函数时创建的,而不是在执行时创建的吗?

不。评估函数定义时,父环境已经存在。父环境是包含函数声明的环境。

在您的示例中:

  • 呼叫makeAdder会创建环境 A ,其中x设置为5
  • 内部函数(function (y) {...})已创建,并获得对 A 的“引用”。
  • makeAdder(内部函数)的返回值已分配给add5
  • 呼叫add5会创建环境 B ,且其父级设置为 A 。之所以可能这样做,是因为该函数在创建时引用了 A
  • B 中查找
  • x。找不到它,因此在已定义它的 B 父级 A 中进行了查找。
  • ...
  

请原谅我只想澄清何时创建父级和本地词法环境的长文本。

ECMAScript中有不同类型的环境,所有环境都是在不同的时间创建的:

  • 声明性环境:所有其他环境的基础,并在评估 block 时创建。
  • 函数环境:在评估函数调用时创建。
  • 全局环境:在评估脚本/初始化运行时时创建。

还有更多,但是这些应该是与此问题最相关的。有关更多信息,请参见https://www.ecma-international.org/ecma-262/8.0/index.html#sec-lexical-environments

但是,在每个给定时间,只有一个 环境是“活动的”(堆栈顶部)。每当创建新环境时,当前活动的环境都将成为其父环境。

The spec defines and uses the following operations for creating new environments

  • NewDeclarativeEnvironment ( E )
  • NewObjectEnvironment ( O, E )
  • NewFunctionEnvironment ( F, newTarget )
  • NewGlobalEnvironment ( G, thisValue )
  • NewModuleEnvironment ( E )

其中E是另一个环境(成为新环境的父级),而F是一个函数对象。 NewFunctionEnvironment从函数对象获取父环境。 NewGlobalEnvironment不接受父环境,因为全局环境不能包含任何父环境。


注意:环境 A 也有一个父级,即全局环境(假设代码是在全局范围内评估的)。全球环境没有父母。