2017-02-18 52 views
1

将for循环块中的所有块作用域变量都挂载在循环标题本身之上?将ES6 javascript块作用域变量挂载到标题中

var x = 4; 

    for(let i = 3; i < x; i++) { 
     let x = 2; 
     ... 
    } 

这应该在每次将x与循环头中的x进行比较时在x上产生死区错误吗?我知道我被推倒在块范围内,但为什么不是x?

+0

你想达到什么目的? – guest271314

+0

我正在添加块范围变量到我的JavaScript数据库解释器,我需要知道如何正确处理这种情况。但是,我认为正确的方法是将循环块嵌套到循环头中。通过这种方式,可以在循环块中看到标题中的“let i”,但循环块中的“let x”在循环标题中不可见。 – Malbrain

+0

不确定是什么问题?如果在'for'循环的外部定义了'var x = 4',为什么要在for循环中定义'let x = 2'? – guest271314

回答

0

for循环块中的所有块范围变量是否悬挂在循环头本身之上?

不,他们都悬挂在该块范围

如果这产生每一次X上的一个死区错误我是相比于环头X?我知道我被推倒在块范围内,但为什么不是x?

没有,因为x在环头被引用定义为4 var x = 4

之前它已被宣布为确定范围和声明之间的时间无法访问let变量x是TDZ。

ex。

console.log(x) // Reference Error, x is in TDZ 
let x = 4 
console.log(x) // --> 4 
0

test run

此基础上,我认为让X只,用于范围内都有效。

0

我误解了,认为只会有一个块范围。我不愿意采用表达式i < x中的两个任意变量,而必须决定查找哪个块范围,这是无法确定的。

正确的方法是构建两个嵌套块作用域,一个用于循环头,一个用于循环体。这意味着let i在循环头文件和循环体范围中均可见,并且循环中的let x仅在循环体范围中可见。容易peasy,柠檬squeezy。

+0

_“正确的方法是构建两个嵌套块作用域”_ for语句不是块,for体不一定是一个。所以例如'for(let i = 0; i <10; i ++)console.log(i);'只创建一个范围,它不是块范围。 – zeroflagL

+0

对,我正是这么说的:循环头创建一个包含'let i = 0;'的范围,在你的情况下,不会有嵌套的循环体范围。但是当循环体是一个块时,它的块范围将被创建,嵌套在循环头域中。 – Malbrain

1

语言规范的相关部分是13.7.4

如果for语句包含letconst声明,然后创建一个范围。

如果for语句包含let声明,则每次迭代都会创建一个作用域。

如果for body是一个块,则创建一个范围。

下面是一些例子和所创建的范围:

//no scope 
for(i = 0; i<3; i++) console.log(i); 

//no scope 
for(var i = 0; i<3; i++) console.log(i); 

//for scope and iteration scope 
for(let i = 0; i<3; i++) console.log(i); 


// for scope, iteration scope and block scope 
for(let i = 0; i<3; i++) { 
    console.log(i); 
} 

为什么我们需要迭代范围?关闭:

for(let i = 0; i<3; i++) { 
    setTimeout(() => console.log(i), 10); 
} 

无迭代范围输出:3,3,3。随着迭代范围:0,1,2

+0

感谢您指出相关的ECMA标准部分。正如我猜测的那样,创建嵌套的作用域,一个用于任何循环头“let”,然后如果需要,第二个嵌套的作用域,用于循环体中的任何'let'。 – Malbrain