ES6块级作用域

ES5中,没有块级作用域,所以会出现以下情况:

        var callbacks = [];
        for(var i=0;i<=2;i++){
          callbacks[i] = function(){
            return i * 2;
          }
        }

        console.table([
          callbacks[0](),
          callbacks[1](),
          callbacks[2](),
        ])

这段代码的结果是输出3个6。

首先var i=0这一句话,将i做了一个变量提升,i是一个跟callbacks平级的变量;
然后进行for循环,for 循环结束时,i的值已经被更新成为了3;
由于function(){return i*2}不是立即被调用的,而是循环结束后,也就是i等于3的时候才调用的,它执行的时候会去找它上一级作用域中i的值,发现i等于3,于是进行计算并输出,所以callbacks[0](),callbacks[1](),callbacks[2]()的结果全部都是6。

ES6中我们可以用let来声明变量,将变量的作用域限定为块级作用域,不存在变量提升:

        const callbacks = [];
        for(let i=0;i<=2;i++){
          callbacks[i] = function(){
            return i * 2;
          }
        }

        console.table([
          callbacks[0](),
          callbacks[1](),
          callbacks[2](),
        ])

结果为0,2,4。
let声明的变量为块作用域,作用于当前块;每次循环都会把值保留下来供后面的闭包使用。
这段for循环等价于:

for (let i = 0; i < 10; i++) {
    a[i] = (function(i) {
        return function(){
          console.log(i);
       }
    })(i);
}

在ES6中只需一个花括号就可以指定块作用域。

{
          function foo(){
            return 1;
          }
          console.log(foo() === 1);

          {
            function foo(){
              return 2;
            }
            console.log(foo() === 2);
          }

          console.log(foo() === 1);
}

结果是打印3个true。
可见两个作用域没有相互影响,一对花括号就已经把作用域隔离。

你可能感兴趣的:(ES6块级作用域)