在JS世界中,我们一般用var来声明变量,但ES6中,新增了let命令,他和var有什么区别呢?
我们来看代码
循环完成之后再进行函数调用,当i的值等于10的时候跳出循环,这时候调用arr[4],也就是调用函数function();i是一个全局变量,刚刚进行循环的时候自增到了10,所以这时候打印出来的结果是10。
我们把var换成let再试一次
结果变成了4,为什么会是4呢?
还记得块级作用域吗?let就是一个块级作用域的变量。
所以当循环执行完毕的时候,for循环外部再也访问不到i了。
当执行arr[i]的时候,调用函数function();函数声明的位置位于i的作用域范围之内,所以i的值就是打印出来的值。
同时,let声明的变量必须先声明再调用,否则会报错,相比于var来说,语法更严格了。
我们再来看一个例子
在for循环的时候打印i的值,猜一下,打印出来的结果是什么?
报错了,i is not defined 停
我的i不是定义了么?在第二行var了一个全局的i,在第三行let了一个局部的i,为什么还会报了一个未定义的错误呢?
我们来看一下究竟是哪里错了
浏览器提醒我第15行出现了错误,可我在第14行明明已经声明了let,为什么还会报错呢?
循环有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
所以第14行的i和第16行的i是没有冲突的,那报错到底是因为什么?算了算了,先把16行的声明注释一下看看吧。
居然可以运行了,证明问题还是出在第16行的let声明上,可到底有什么错呢?
ES6 明确规定,如果区块中存在和命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
原来,只要在块级作用域内声明let变量,那么变量就不受外界的影响。
for循环的{}已经属于子作用域了,如果子作用域里面没有声明变量,可以读取到父作用域i的值,如果子作用域里面声明了变量,那么变量就不再受父作用域声明的变量的影响了,而是根据子作用域声明的变量而影响,还记得前面说过什么吗?变量必须先声明再赋值!所以子作用域里面是一个全新的作用域,不受外界的影响,当浏览器运行到console.log(i)的时候还没有声明i这个变量,就报了i is not define的错了,我们再来调整一下代码的顺序试一下
看,成功打印出来了,子作用域内声明变量之后,里面的i就都被赋值成了1,最后一次调用打印的结果也是1。如果里面没有重新声明变量i的话,子作用域内是可以访问到父作用域的i的,打印出来的结果就是0-9和1了。
我们再来看一个例子
这次打印的结果会是什么呢?
看上去好像是1吧。
噢我的天,又报错了,这是为什么呢?
原来,ES6不允许let在相同的作用域内,同时声明一个变量,既然var过了,何必在let一下呢?
再来看今天最后一个例子
varb=1;
functionfn(){
leta=2
return function(){
console.log(b)
}
letb=3
}
fn()()
你们猜这次打印出来的结果会是什么呢?
算了算了,我们还是先仔细分析一下吧。
在函数fn的作用域内声明了a和b两个变量,所以现在函数内是读不到var的b了。之后进行函数调用,声明了变量a之后进行赋值,然后就return了,什么?然后就return了,所以let b=3这行代码根本没走到,所以这时候是访问不到b的,return了一个函数,函数里面打印b,当然是报错了,因为根本就没走到声明变量的代码,所以这时候属于未声明,先调用。应该会报b is not defined的错,我们打开浏览器看一下吧。
到这里,今天小编就要和大家说再见了。
恭喜你,已经掌握let的一部分精华了,剩下的内容,明天不见不散哟......
领取专属 10元无门槛券
私享最新 技术干货