浅谈JS中let(一)

在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的一部分精华了,剩下的内容,明天不见不散哟......

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180508G1RA2G00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券