在ES5中我们用var关键字来声明一个变量,但var的设计可以说成时javascript上的一个设计失误,但这种失误因为浏览器的解析和开发者的问题多半不能修复和移除,需要向后兼容。
而在十多年前,Brendan Eich就决定修复这个问题,于时他添加了一个新的关键字let
我们可以将它看做更完美的var
之所以说var是一个失误,是因为它没有作用域的概念
变量的作用域就是指变量在什么范围内是可用的
{
var name = "xiufan";
console.log(name);
}
console.log(name);
我们运行上面的js代码后,控制台会输出两个xiufan这意味着我们在“{}”使用var定义的变量name在“{}”外面也是可用的,这是不符合我们的编程思想的。
当我们在某个块中定义了一个变量,我们希望它只能在当前的块中使用,这个块就是变量的作用域,若没有作用域的概念,那我们可以在任何地方修改这个变量的值,造成代码的污染。
一个简单的列子:
我们通过for循环为5个按钮绑定点击事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
<script type="text/javascript">
var btn = document.getElementsByTagName("button");
for (var i = 0 ; i < btn.length ; i++) {
btn[i].onclick = function(){
console.log(i)
}
}
</script>
</html>
运行代码后我们无论点击哪一个按钮,输出的都是5
第一次循环
为第一个按钮绑定事件,此时输出的i为1
text 代码:btn[0].onclick = function(){ console.log(0) }
第二次循环
为第二个按钮绑定事件,此时输出的i为1
text 代码:btn[1].onclick = function(){ console.log(1) }
但每次输入的i都是同一个i,第二次循环后i的值会变为2,这意味这btn[0]的输出结果将由0改为1。第三次循环后i的值变为3,此时btn[0]、btn[1]、btn[2]输出的值都是3....
text 代码:
循环一次btn[0].onclick = function(){ console.log(0) }
循环两次
text 代码:btn[0].onclick = function(){ console.log(1) } btn[1].onclick = function(){ console.log(1) }
循环三次
text 代码:text 代码:btn[0].onclick = function(){ console.log(2) } btn[1].onclick = function(){ console.log(2) } btn[2].onclick = function(){ console.log(2) }
......
在ES5中的解决方法-->闭包
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</body>
<script type="text/javascript">
var btn = document.getElementsByTagName("button");
for (var i = 0 ; i < btn.length ; i++) {
(function(i){
btn[i].onclick = function(){
console.log(i)
}
})(i)
}
</script>
</html>
通过一个立即执行函数将i保存在它的作用域中,这样每次循环后立即执行函数中i的值都不会被改变。
但使用ES6的语法,只需要将var改为let即可。
text 代码:for (let i = 0 ; i < btn.length ; i++) { btn[i].onclick = function(){ console.log(i) } }