浏览器内部如何描述作用域,这个for循环是不是相当于产生了 btns.length个作用域,在这些作用域里有一个变量i,有一个具体值,分别是1,2,3,4,5等等,这个作用域是在栈中的一个具体空间吗?
补充一下完整代码
这段代码for循环如果用var,点击直接报错
如果使用let,是一段正常代码,
浏览器内部如何描述作用域,这个for循环是不是相当于产生了 btns.length个作用域,在这些作用域里有一个变量i,有一个具体值,分别是1,2,3,4,5等等,这个作用域是在栈中的一个具体空间吗?
补充一下完整代码
这段代码for循环如果用var,点击直接报错
如果使用let,是一段正常代码,
变量i绑定到了for循环每次迭代的块作用域中,在上一个循环结束的时候,进行重新赋值
它的执行过程像这样:
{
let j;
for (j=0; j<10; j++) {
let i = j; // 每个迭代重新绑定!
console.log( i );
}
}
补充:
如果你想使用var,可以这样:
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = (function (j) {
return function () {
console.log(j);
btns[j].style.backgroundColor = 'red';
};
})(i);
}
在IIFE里传一个参数进去,这样,每次循环都创建一个新的作用域,并把它封闭在闭包里,每次循环也都会有一个正常都值了
首先回答问题:该i确实是在一个作用域中,且该作用域因为引用的关系而不会被删掉,假如说的栈是js的存储类型的话,那这个栈是指存的i,而如果栈指的是作用域链的话,那前面的回答就足够了。
接着说下这个代码的关键点,每次console.log会输出btns.length的值。
还是深刻理解JS的花括号吧。
{
const a = 'Hi';
}
console.log(a);
以上代码运行结果是打印'Hi'吗?当然不是,a是undefined。
花括号代表了作用域是相当顶级的规则,因此for(...){}
中,括号中的内容属于外部域,花括号内是内部域。且同样遵循内部域可以直接调用外部域中已声明的变量的规则。
var现在已经不推荐使用了,还是与时俱进吧。而且建议初学者应该学习“应该怎样用”而不是“不报错就好”。从你的代码看是想点击哪个哪个变红,而且是abcd四个button的话,难道是选择题的答案处理?那怎么单选?选中了怎么取消?这些都是要处理的,可不是现在这几行能搞定的。
已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
来看这一段代码,发现了什么?第二个
let i
居然没报错,那说明for
作用域和for
循环体作用域不同。因为如果是同一个作用域是不能对同一个变量声明多次的,比如下面这个就会报错尝试下面这段代码也可以发现两个 i 是不同的
然后是一个比较神奇的事情
这段代码可以打印出 0~4,但是
这段代码打印出来全是 5
这说明 for 作用域和 for 循环体作用域并不只是两层作用域那么简单。从效果上来看,for 作用域中的变量在其循环体作用域中会有一个副本,所以延迟打印才不会总是打印出最后一个值。注意:我说的是从效果上看。本质是怎么回事,不敢妄加揣测,最好还是去 ECMA-262 中找找答案。