ES6之前js没有块级作用域,它使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域,用var声明的变量具有变量提升(declaration hoisting)的效果。ES6新增加了一个let,可以在{}, if, for里声明。用法同var,但作用域限定在块级,let声明的变量不存在变量提升。
例1: 块级作用域 if
function test(flag) {
if (flag) {
var a = 'js'
}
// 这里也可以访问 a
}
变量a在if块里声明的,但在else块和if外都可以访问到val,把var换成let后:
function test(flag) {
if (flag) {
let a = 'js'
}
// 这里也访问不到 a
}
例2块级作用域 for
for(var i=0; i<2; i++){
console.log('outer i: ' + i);
for(var i=0; i<2; i++){
console.log('inner i: '+i);
}
}
执行结果如下:
outer i: 0
test.html:12 inner i: 0
test.html:12 inner i: 1
可以看到,外层循环被打断了,因为i为全局变量所以 i 的值被内层循环修改了,把内层循环的var换成let后:
for(var i=0; i<2; i++){
console.log('outer i: ' + i);
for(let i=0; i<2; i++){
console.log('inner i: '+i);
}
}
执行结果如下:
outer i: 0
test.html:12 inner i: 0
test.html:12 inner i: 1
test.html:10 outer i: 1
test.html:12 inner i: 0
test.html:12 inner i: 1
示例3: 变量提升
先使用后声明
console.log(a) // undefined
var a;
变量val先使用后声明,输出undefined,也不报错。把var换成let,就报错了
console.log(a) // Uncaught ReferenceError: a is not defined
var a;
先判断后声明
if (typeof a == 'undefined') {
// ...
}
var a = ''
把var换成let,if处报语法错 Uncaught ReferenceError: a is not defined
if (typeof a == 'undefined') {
// ...
}
var a = ''
ES6规定,如果代码块中存在let,这个区块从一开始就形成了封闭作用域,凡是在声明之前就使用,就会报错。即在代码块内,在let声明之前使用变量都是不可用的。