规范

2016-11-19 78 views
11

“LexicalEnvironment”和“VariableEnvironment”之间的区别我正在阅读ECMAScript 2015 specification,术语“LexicalEnvironment”和“VariableEnvironment”多次使用。它们在表23中定义:规范

LexicalEnvironment:标识用于解析此执行上下文中由代码生成的标识符引用的词法环境。

VariableEnvironment:标识其EnvironmentRecord在此执行上下文中保存由VariableStatements创建的绑定的词法环境。

执行上下文的LexicalEnvironment和VariableEnvironment组件始终是词法环境。当创建执行上下文时,其词法环境和变量环境组件最初的具有相同的值

所以,我想知道他们将如何不同,以及每种情况下使用哪些情况。任何人都可以解释吗?

+0

[在ECMAScript 5中的“LexicalEnvironment”和“VariableEnvironment”之间的差别的澄清的可能性重复](http://stackoverflow.com/q/15031667/1048572)?它们的目的并没有真正改变,只有当前的词汇环境更频繁地交换(例如,每个块范围)。 – Bergi

+0

是的,我之前读过它,但我仍然遇到一些麻烦。你说'尝试{抛出'一些“} catch(x){function y(){console.log(x,typeof x);} y(); }',我在chrome中运行它,但没有'抛出一个ReferenceError for x'@ Bergi –

+0

@SmallTownNE谢谢,我更新了[回答](http://stackoverflow.com/a/15035083/1048572)。但是,“有趣的事实”并不是帖子的要点 - 主要的一点是,当你输入一个块范围时,LexicalEnvironment会改变(例如'catch',因为ES6也是普通块 - 对于'let'和'const'等) – Bergi

回答

6

我张贴the question到官方在github ECMA262组织,这就是答案littledan:

LexicalEnvironment是一个本地词法范围,例如,用于定义的变量。如果使用放入catch块来定义一个变量,它只能在catch块中可见,并且要在规范中实现,我们使用LexicalEnvironment。 VariableEnvironment是var-defined变量等事物的范围。变量可以被认为是“提升”到函数的顶部。为了在规范中实现这个功能,我们给函数一个新的VariableEnvironment,但是说block会继承封闭的VariableEnvironment。

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 EnvironemntVariable EnvironmentExecution Contexthoisting

console.log(myVar); // undefined 
 
var myVar = 'hello'; 
 
console.log(myVar); // hello

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

BU再向您:

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 ?

+0

感谢您的回复,我更新我的问题 –

+0

你是对的,谢谢你的建议。 –