ES6之前js没有块级作用域,它使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域,用var声明的变量具有变量提升(declaration hoisting)的效果。ES6新增加了一个let,可以在{}, if, for里声明。用法同var,但作用域限定在块级,let声明的变量不存在变量提升。
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 }
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
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声明之前使用变量都是不可用的。