我一直试图理解在js中创建词法环境的时间。据我所知,词汇环境是在创建阶段和执行阶段两个阶段创建的,但请看下一个简单的闭包。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
所以,当makeAdder返回函数时,它返回的函数带有指向x的父词法环境,但是我不明白的是为什么add5已经有一个父词法环境,而返回的内部函数甚至没有已经执行了,所以我可以推断的是,一旦遇到函数定义(返回函数),便附加了父词法环境,这是正确的吗?父词法环境是在代码中声明并到达函数时创建的,而不是在执行时创建的?以及返回的函数的词法环境如何,在执行add5函数时会创建其词法环境。请原谅我只想澄清何时创建父级和本地词法环境的长文本。
先谢谢大家。
答案 0 :(得分:1)
所以我可以推断的是,一旦遇到函数定义(返回函数),便附加了父词法环境,这是正确的吗?
是的,附加到新创建的功能对象上。
父词汇环境是在代码中声明并到达函数时创建的,而不是在执行时创建的吗?
不。评估函数定义时,父环境已经存在。父环境是包含函数声明的环境。
在您的示例中:
makeAdder
会创建环境 A ,其中x
设置为5
。function (y) {...}
)已创建,并获得对 A 的“引用”。makeAdder
(内部函数)的返回值已分配给add5
。add5
会创建环境 B ,且其父级设置为 A 。之所以可能这样做,是因为该函数在创建时引用了 A 。x
。找不到它,因此在已定义它的 B 父级 A 中进行了查找。请原谅我只想澄清何时创建父级和本地词法环境的长文本。
ECMAScript中有不同类型的环境,所有环境都是在不同的时间创建的:
还有更多,但是这些应该是与此问题最相关的。有关更多信息,请参见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 也有一个父级,即全局环境(假设代码是在全局范围内评估的)。全球环境没有父母。