【发布时间】:2017-01-10 12:59:23
【问题描述】:
以下代码抛出 ReferenceError 'a is not defined'。
{
let a = 'a1';
{
console.log(a);
let a = 'a2';
}
}
下一个也是。
{
const a = 'a1';
{
console.log(a);
const a = 'a2';
}
}
如果您改为使用 var 声明,它会按我的预期工作。 (没有抛出错误错误并记录了“a1”。)
当我尝试分析以下代码时,我变得更加难以理解。
{
let a = 'a1';
{
console.log(a);
var a = 'a2';
}
}
它抛出一个 SyntaxError,“标识符 'a' 已被声明”。
我很天真地希望标识符会被隐藏直到一个 let 或 const 声明之后,就像 Clojure 中的 let 或 Racket 中的 let* 的行为一样。作为described clearly on MDN,这不是它的工作原理。
但是为什么它会这样工作?为什么 Racket 同时具有 let 和 let* 形式?
【问题讨论】:
-
感谢您的链接,但它没有回答我的问题。我了解它如何 工作,但不了解为什么 选择此模型。是因为性能问题吗?
-
SO 不是问为什么语言具有特定功能或行为的地方。问TC-39,他们不假思索地知道。我可以推测一下。也许提升机制被发现如此重要,以至于它比外部范围变量更受欢迎?
-
@JohanJonasson 为什么选择它?因为 ES6 中的作用域总是基于块/函数体,
let没有引入新的作用域。例如,这确实允许相互递归声明而没有额外的麻烦。此外,当您不确定它所指的是哪个变量时,根本不提供a也不太容易出错。 -
感谢@Bergi,这是一个有趣的答案。如果我理解正确的话,每个 let/const 声明都必须引入一个新的范围,如果它们的行为方式符合我的预期?
标签: javascript scope ecmascript-6