JS变量如何覆盖工作?

时间:2017-04-01 13:11:05

标签: javascript ecmascript-6

此代码可以正常工作:

const a = 1;
{
  const b = a; // let's use "a" in a sub-scope
}
{
  const a = 2; // let's override "a" in another sub-scope
}

...但此代码在第3行失败并显示a is not defined

const a = 1;
{
  const b = a; // let's use "a" in a sub-scope <<< CRASH!! >>>
  const a = 2; // let's override "a" in the same sub-scope
}

我在node 7.7.4上对此进行了测试。它可能只与V8有关,我很好奇Firefox如何处理这个问题。

它与JS规范中定义变量声明的方式有关吗? const/let没有悬挂,但是&#34;某些东西&#34; (一些元数据?)似乎仍然悬而未决,否则我们就没有问题了。

2 个答案:

答案 0 :(得分:2)

吊装是指变量声明被提升到变量范围顶部的概念。

更准确地说,JavaScript的两个过程中构建它的执行环境是一个副作用。

第一遍设置所有函数和变量声明。在此阶段,声明变量但未定义变量,声明和定义函数声明(即函数声明function fnName(){...} 变量函数表达式:var fnName = function (){...})。

第二遍然后使用可用的声明函数和变量(当前未分配,因此具有未定义的值)执行代码。

var function 作用域,而不是块作用域。  虽然letconst允许声明块作用域变量,但代码是使用两个执行过程构建的。区别在于块范围应该在它们自己的范围内的第一遍中被考虑(块范围或其他)。

为了说明这一点,请考虑您的第二个片段。

代码在第二种情况下抛出错误,因为在第一次传递后它可以重写为:

// const 'a' declared in this outer scope
const a:
a = 1; 

{ 
  // separate const 'a' declared in this block scope
  // Declarations still hoisted for this block scope
  const b, a
  b = a; // a undefined here
  a = 2;
}

答案 1 :(得分:1)

根据ES6规范,使用letconst进行变量声明。 它们都是 Block Scoped 范围内声明之前的时间是temporal dead zone。 根据文件:

  

在ECMAScript 2015中,让我们将变量提升到顶部   块。但是,在之前引用块中的变量   变量声明导致ReferenceError。变量在a中   &#34;时间死区&#34;从块的开始直到声明   处理完毕。

正如@Bergi所说,它是实际声明之前的时间