geo*_*org 2 javascript ecmascript-6
考虑一下:
'use strict';
{
let p = 1;
{
console.log(p);
let p = 2;
}
}Run Code Online (Sandbox Code Playgroud)
一种直觉告诉我们它应该记录"1"(因为var必须在重新声明之前保留其旧值).但是,实际结果是ReferenceError.这是为什么?(将基于标准的解释).
请注意我已p在外部范围内声明,因此它在内部块中已知.如果你注释掉这p=2条线,一切都运转正常.
作为验尸记录,虽然这种行为似乎有记录,但它仍然非常违反直觉,参见 这个C代码:
void main() {
int p = 1;
{
printf("%d\n", p); // prints '1'
int p = 2;
}
}
Run Code Online (Sandbox Code Playgroud)
还有另外一个JS fuckup特别注意!
Ste*_*han 12
据MDN称:
在ECMAScript 2015中,让绑定不受变量提升的约束,这意味着让声明不会移动到当前执行上下文的顶部.在初始化之前引用块中的变量会导致ReferenceError(与使用var声明的变量相反,该变量将具有未定义的值).变量在块的开始处于"临时死区",直到处理初始化为止.
问题是你的let p语句创建了一个新变量,其范围是整个代码块.所以p在console.log(p)中; 是指新创建的变量.
提供了与您的情况类似的示例:
function test(){
var foo = 33;
if (true) {
let foo = (foo + 55); // ReferenceError
}
}
test();
Run Code Online (Sandbox Code Playgroud)
由于词法作用域,表达式(foo + 55)中的标识符"foo"评估为if块的foo,而不是值为33的上覆变量foo.在那一行中,if块的"foo"已经已经在词法环境中创建,但尚未达到(并终止)其初始化(这是语句本身的一部分):它仍然处于时间死区.