每个函数调用/执行都会创建一个新的执行上下文,并带有一个全新的VariableEnvironment和LexicalEnvironment对象实例,以表示该函数内的代码/变量。 (对于本篇文章,我将把这两个简写为Var / LexEnvironment)
这些新的Var / LexEnvironment对象还包含对表示功能对象外部作用域的已经创建的 Var / LexEnvironment对象的引用。这是范围链。
VariableEnvironment
保留函数作用域变量状态。
LexicalEnvironment
保存块{}范围变量状态。
假设我们有两个函数:包含function1的function0。
调用function1时,将创建一个新的执行上下文=通过function1中的代码创建全新的Var / LexicalEnvironment实例:
每个*块{}仅一个VariableEnvironment实例和一个LexicalEnvironment实例。
仅指出现有的词汇环境(外部)。 (这就是所谓的“范围链”)。运行包含function1的外部词汇环境的function0,您将获得外部Var / LexEnvironments的全新实例。
但是function1对外部词汇环境的引用没有改变。它们不会成为这些新的Var / LexEnvironments实例。
一个函数的[[Scopes]]
属性=与此函数对象相关的Var / Lexical环境的表示形式=浏览器对ECMA规范中定义的[[Environment]]属性的表示形式。
您可以在浏览器控制台中使用console.dir(funcName)
进行查看。
这里有什么不对的地方?我想念什么?
Tl; dr:
将JS代码中的所有内容都视为执行上下文(全局或函数或eval()执行上下文)的属性似乎是安全的。为什么?
每个执行上下文都有唯一的词法/变量环境作为属性。 (新运行=新ex。上下文= variableEnv对象的新实例=具有新引用的新变量)
,这些词法/变量环境包含所有变量(标识符-值映射)。
function function0(sizevar) {
s = sizevar * 2
return function function1() {
console.log(s)
console.log(sizevar);
};
}
var size12 = function0(12);
var size14 = function0(14);
因此,从上面^,当您返回嵌入式功能1时,您将返回对函数实例/对象的引用,该实例是一个特定执行上下文的词法/变量环境的属性。
并且当function0()返回function1()时,作用域链将绑定到执行上下文的状态(即其variableEnv),即使该执行上下文已执行完毕。