ES5之前存在的问题:因为if和for都没有块级作用域的概念,所以很多时候都必须借助函数的作用域来解决使用外面变量的问题。
// 1.变量作用域:变量在什么范围内可用,但是使用var时没有作用域,上述都能够打印出why
{
var name = 'why';
console.log(name);
}
console.log(name);
```javascript
//2没有块级作用域引起的问题:if的块级
var fun;
if(true){
var name='lee';
fun = function(){
console.log(name);
}
fun();//打印出lee
}
//假如在外面使用fun(),本意想输出if中的name,
//但是name在外面可以任意改变
name='修改lee';
fun();//修改lee
//3没有块级作用域引起的问题:for没作用域,经典按钮问题
var btns = document.getElementsByTagName('button');
for(var i = 0;i<btns.length;i++){
btns[i].addEventListener('click',function(){
console.log(i);
})
}
// 不管点击什么按钮都是5
// i循环结束后变成五,又由于for没有块级作用域问题,不会将每次的i保存在作用域中,最后点击的时候,i就从外面获取i的值,而此时i已经变为5了,在真正使用i之前,i发生了改变。与上述if的例子相同,i值可以在下次循环的时候发生改变,而不会保持原来在一个for循环中的值。
以前解决办法:写闭包,因为函数具有作用域:
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
(function (i) {
btns[i].addEventListener('click', function () {
console.log(i);
})
})(i)
}
相当于:
function(i){//i=0
btns[i].addEventListener('click', function () {
console.log(i);
})
}
function(i){//i=1
btns[i].addEventListener('click', function () {
console.log(i);
})
}
ES6中,加入了let,let是有if和for的块级作用域
var btns = document.getElementsByTagName('button');
//将var i = 0 改为 let i = 0 就可以实现功能
for(let i = 0;i<btns.length;i++){
btns[i].addEventListener('click',function(){
console.log(i);
})
}
由于let具有块级作用域,相当于(都有自己独立的作用域):
{i=0
btns[i].addEventListener('click', function () {
console.log(i);
})
}
{i=1
btns[i].addEventListener('click', function () {
console.log(i);
})
}