Js中常用 var 来声明变量,var 声明变量的问题:
- 可以重复声明
- 没有块级作用域(es5中只有全局作用域和函数作用域)
- 不能限制修改
ES6中用 let 声明变量,用 const 声明常量,let 和 const只能声明一次,禁止重复声明;const 声明变量时,必须同时初始化,定义后不能通过再次赋值改变;const定义一个常量,这个常量也可以是数组、对象,数组和对象内部的值可以改变,引用地址不变;let 和 const 支持块级作用域
块级作用域 ({}):
定义:是一个语句,将多个操作封装在一起,通常是放在一个大括号里,没有返回值。
特点:
外层作用域无法获取到内层作用域的变量
if(true) {
let a = 10;
}
console.log(a); //报错: a is not defined
内层作用域可以定义与外层作用域同名的变量
{
let a = 1;
if(true) {
let a = 20;
console.log(a); //输出20
}
console.log(a); //输出1
}
let使用经典案例:let命令替代闭包
html:
<input type="button" value="按钮1">
<input type="button" value="按钮2">
<input type="button" value="按钮3">
<input type="button" value="按钮4">
js:
window.onload = function() {
var aBtn = document.getElementsByTagName("input");
for(var i =0; i < aBtn.length; i++) {
aBtn[i].onclick = function() {
console.log(i);
}
}
}
我们希望在点击每一个按钮时,弹出该按钮对应的索引,但是上面的js执行时,无论点击哪个按钮,都只会弹出4。这是因为,Js中的 for() {} 不是块级作用域,所以最内层定义的 function 中调用的 i 其实是循环里面定义的 i 。 这个 i 在循环结束后就等于 4. 当每次点击时输出的都是console.log(4)
传统的解决方法,是采用闭包:
window.onload = function() {
var aBtn = document.getElementsByTagName("input");
for(var i = 0; i < aBtn.length; i++) {
aBtn[i].onclick = (function(i) {
return function() {
console.log(i);
}
}(i));
}
}
es6中利用 let 解决:
window.onload = function() {
var aBtn = document.getElementsByTagName("input");
for(let i = 0; i < aBtn.length; i++) {
aBtn[i].onclick = function() {
console.log(i);
}
}
}
//for每次循环生成一个新的作用域
//fuction内的i访问的是这个作用域内的i