ECMAScript -- let 和块级作用域
什么是块级作用域?js中有块级作用域吗?
- 块级作用域,指代码中用{}括起来的范围,如下代码所示:
// if语句
if(true){
console.log('block')
}
// for语句
for(var i =0;i<10;i++){
consolo.log(i)
}
- 在es2015之前,是没有块级作用域的概念的,即块是没有其独立的作用域的,导致在块中定义的成员可以被外部访问
if(true){
var a='aaa'
}
console.log(a)
// 输出:
// aaa
像上面这样的情况,在代码量大的情况是很不安全的,也很难维护
- 在es2015后,出现了let 关键字,用let声明的变量是只能在其被声明时的代码块中被访问
if(true){
let a ='aaa'
console.log('块中的a:'+a)
}
console.log(a)// 会报错,a is not defined
let 的作用
- 适用于声明for循环中的记数器
es2015前,嵌套的for循环必需要为每层循环设置不同的记数器名称,不然会出现意料之外的情况
for(var i=0;i<3;i++){
for(var i=0;i<3;i++){
console.log(i)
}
}
// 输出:
// 0
// 1
// 2
很显示,我们认为的是会输出9次结果,然而并不是,因为两层循环使用相同的i,并且不是使用var定义,即没有块级作用域,那么内层循环的i会覆盖外层循环的i,导致当内层循环完成时,i变成3了,外层循环的i也是3,将不满足循环条件而直接结束循环
es2015后,使用let关键字使得嵌套的for循环可以为每层循环设置相同的记数器名称
for(let i=0;i<3;i++){
for(let i=0;i<3;i++){
console.log(i)
}
}
// 输出:
// 0
// 1
// 0
// 1
// 2
// 0
// 1
// 2
因为使用let产生了块级作用域,内层循环不会影响外层循环,但是平时开发中还是不建议使用同名的记数器,同名计数器不利于我们后期去理解代码,造成维护困难
let 没有变量提升
在es2015之前 ,var 定义变量可以在使用之后,因为默认的var 变量的定义会被提升到作用域前部,而使用let后,在使用后再定义变量会报错
console.log(foo) //输出undefined, 定义被提升,但是赋值不会提升
var foo='abc'
console.log(foo) //会报错,因为foo在此前未定义
let foo='abc'