我正在阅读ECMAScript 2015 specification和条款" LexicalEnvironment"和"变量环境"多次使用。它们在表23中定义:
LexicalEnvironment:标识用于解析此执行上下文中的代码所做的标识符引用的词法环境。
VariableEnvironment:标识其EnvironmentRecord包含由此执行上下文中的VariableStatements创建的绑定的词法环境。
执行上下文的LexicalEnvironment和VariableEnvironment组件始终是Lexical Environments 。创建执行上下文时,其LexicalEnvironment和VariableEnvironment组件最初具有相同的值。
所以,我想知道它们将如何不同,以及每种情况都会被使用。有人可以解释一下吗?
答案 0 :(得分:7)
这很难。我将尝试用一些简单的例子来解释。所以一件重要的事情,在这个问题上也要理解execution context
。
词汇环境
意味着你在代码中写一些内容很重要。并非所有编程语言都是这样,但javascript是。
所以,如果你有像
这样的功能function hello() {
var myVar = 'hello';
}
现在变量myVar
在词法中位于函数内部。这就是你正在编写的代码。
简而言之,如果谈论lexical environment
意味着它的写作地点和周围的地方。
可变环境
每次调用函数时,都会创建一个新的执行上下文。所以即使myVar被宣布3次(见下一个例子)他们也没有互相接触。当你谈到Variable Environment
时,那就是
function b() {
var myVar;
console.log('three', myVar) // three undefined
// cause myVar is newly declared in b()
// but has no value
}
function a() {
var myVar = 2;
console.log('two', myVar) // two 2
b();
}
var myVar = 1;
console.log('one', myVar) // one 1
a();
console.log('four', myVar) // one 1

现在你在哪里要求差异,我想这只是关于两件事的理论讲座。但是lexical environment
有点知道变量在内存中的位置。
这实际上就是你问题的答案。但我会展示一些更多的例子,以确定误解可能导致的问题。
因为在javascript中还有一个名为hoisting
的东西,如果你在错误的地方编写代码,它会给你带来错误。它可能有奇怪的行为。接下来的示例实际上非常简单,但都取决于Lexical Environemnt
,Variable Environment
,Execution Context
和hoisting
console.log(myVar); // undefined
var myVar = 'hello';
console.log(myVar); // hello

但
function a() {
console.log(myVar) // gives Error myVar is not defined
}
a();

但又一次:
function a() {
console.log(myVar); // undefined no Error
// cause it would take myVar from global
// execution context
// but also no error cause we define it again
// in this function (hoisting)
var myVar = 0; // define myVar newly in this lexical environment
console.log(myVar); // 0
}
var myVar = 'hello';
a();
console.log(myVar); // hello

但是如果我们这样做的话再次
function a() {
myVar = 0; // overwrite global myVar
console.log(myVar); // 0
}
var myVar = 'hello';
a();
console.log(myVar); // 0 did you expect myVar to be 0 ?

答案 1 :(得分:7)
我将the question发布到github上的官方ECMA262组织,这是littledan的答案:
LexicalEnvironment是一个本地词法范围,例如,用于自定义变量。如果在catch块中使用let定义变量,它只在catch块中可见,并且为了在规范中实现,我们使用LexicalEnvironment。 VariableEnvironment是var定义变量之类的范围。 vars可以被认为是“悬挂”到函数的顶部。为了在规范中实现这一点,我们为函数提供了一个新的VariableEnvironment,但是说块继承了封闭的VariableEnvironment。