ES6初探-let与块级作用域

来源:互联网 发布:服务器linux系统 编辑:程序博客网 时间:2024/05/20 08:45


很久没有写博客,日子一天天过得很快,觉得有时候写点东西会让人沉静下来边思考边整理,一直纠结let是个什么东西,看了些面试题好多都关于这个的,今天终觉恍然大悟啊,然后整个人就开心起来了,终究学习还是使人快乐啊!

    进入正题吧~~

首先我们说一下块级作用域的定义:任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。

/*利用匿名函数表达式可以模拟出块级作用域*/      (function (){          var i = 100;          console.log("block:" + i);      })();    

   除此之外我们可以用let来实现块级作用域。

  ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。


没有块级作用域会带来什么样的麻烦呢?

1.由于ES5只有全局作用域和函数作用域,没有块级作用域,会带来很多问题,比如说向下面的例子,内层变量可能会覆盖外层变量。


var tmp = new Date();function f() {  console.log(tmp);  if (false) {    var tmp = 'hello world';  }}f(); // undefined

上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。


2.用来计数的循环变量泄露为全局变量。

var s = 'hello';for (var i = 0; i < s.length; i++) {  console.log(s[i]);}console.log(i); // 5
上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。


let实现块级作用域例子:

function f1() {  let n = 5;  if (true) {    let n = 10;  }  console.log(n); // 5}
上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var定义变量n,最后输出的值就是10。


let声明变量的特点:

     1.var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

    

// var 的情况console.log(foo); // 输出undefinedvar foo = 2;// let 的情况console.log(bar); // 报错ReferenceErrorlet bar = 2;


     2.只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;if (true) {  tmp = 'abc'; // ReferenceError  let tmp;}

       上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。


      3.let不允许在相同作用域内,重复声明同一个变量。

 

/ 报错function () {  let a = 10;  var a = 1;}// 报错function () {  let a = 10;  let a = 1;}

以上是学习自阮一峰老师的ECMAScript 6入门,我觉得介绍得非常清楚,适合对初学ECMAScript 6的孩子们。网址:http://es6.ruanyifeng.com/