ES6出现之前,只有函数可以形成作用域。而ES6中新增了块级作用域概念。
let
**和**const
**命令可以构成一个块级作用域**。
用法类似var
,声明一个块作用域内的变量,注意,块作用域外无法访问该变量。用法如下:
// 在if语句中定义块作用域
var check = true;
if (check) {
let value = 6;
}
console.log(value); //undefined
// 在循环中定义块作用域
for(let i =0; i < arr.length; i++) {...}
与var
不同之处:
var temp = 1;
if (true) {
console.log(temp); //ReferenceError: 用let声明的temp变量会绑定该块作用域
let temp = 2;
}
if (true) {
let a = 1;
let a = 2; //throw error: Duplicate declaration "a"
}
有了块级作用域,可以避免内层变量覆盖外层变量,可以让变量应用到更小范围内。
下面让我们看一道经典的闭包问题,思考如何用let
解决?例题如下:
var a = [];
for (var i =0; i <10; i++){
a[i] = function(){
console.log(i);
}
}
a[6](); // 10
由于变量i
是全局变量,所有每一次循环,新的i
值都会覆盖老的i值,导致最后数组a
的每个元素运行结果都是10。
如果使用let
,i
变量的作用域范围只限于块作用域,即每次循环的代码块,如此一来,最后a[6]()
可以返回期望值:6。修改如下:
var a = [];
for (let i =0; i <10; i++){
a[i] = function(){
console.log(i);
}
}
a[6](); // 10
const用来声明常量,一旦定义,就不能修改。
这里需要注意,如果const声明的是对象,那么,变量名指向的是对象地址。所以,对象地址不允许修改,但是,对象的值,是可以修改的。
例如:
const foo = {a: 1};
foo.b = 3; // 正确
foo = {b: 6}; // throw error: "foo" is read-only
块级作用域的出现,帮助解决了很多和变量作用域相关的问题!让我们好好享受这个新特性吧!