es6——块级作用域

1.var声明及变量的提升机制

  在函数作用域或者全局作用域中通过var声明的变量,都会被当成在当前作用域顶部声明的变量

  例:

    function getValue(condition) {           

      if (condition) {                

        var  value = "blue";               

        return value;                  

      } else {                        

        // 此处可访问变量value,其值为undefined                 

        return null;                             

      }                                   

      // 此处可访问变量value,其值为undefined         

    }

  上述相当于:

    function getValue(condition) {  

      var  value;         

      if (condition) {                

        value = "blue";               

        return value;                  

      } else {                        

        // 此处可访问变量value,其值为undefined                 

        return null;                             

      }                                   

      // 此处可访问变量value,其值为undefined         

    }

 

 

2.块级声明

  1)用let和const声明变量,可以把变量的作用域限制在当前代码块(a.函数内部,b.块中(字符{和}之间的区域))中,而且声明的变量不会提升,作用域之外无法访问作用域内定义的变量

   

  例:

    function getValue(condition) {                       

      if (condition) {

        // 此处为临时死区(Temporal Dead Zone),使用console.log(typeof  value)语句会抛出错误。因为JavaScript引擎在扫描代码发现变量声明时,要么将它们提升至作用域顶部(遇到var声明),要么将声明放到TDZ中(遇到let和const声明)。访问TDZ中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从TDZ中移出,然后方可正常访问。

        let  value = "blue";

        return value;

      } else {

        // 变量value在此处不存在

        return null;

      } 

      // 变量value在此处不存在

    }

 

  2)禁止重声明:同一作用域中不能用let或者const重复定义已经存在的标示符

    例: var count = 30;

      // 抛出语法错误

       let  count = 40;

  

  3)const声明

    const声明的是常量,其值一旦被设定后不可更改。因此,每个通过const声明的常量必须进行初始化

      例: const  maxItems = 30;

        const name;// 语法错误:常量未初始化

    const声明和let声明有一处很大的不同,即不可以为const定义的常量再赋值,否则会抛出错误

    const声明不允许修改绑定,但允许修改值。即用const声明对象后,可以修改该对象的属性值

 

3.循环中的块作用域绑定

  var  funcs = [ ];

  for (let i =0; i< 10;i++){      // 注:此处若用const声明,则会抛出错误。因为在循环的第一个迭代中,i是0,迭代执行成功。然后执行i++,因为这条语句试图修改常量,因此抛出错误。

    funcs.push(function() {      所以,如果后续循环不会修改该变量,那可以使用const声明,即在for-in或者for-of循环中使用const时的行为与使用let一样。

      console.log(i);

    });

  }

  funcs.forEach(function(func) {

    func(); // 输出0,然后是1、2,直到9; 若用var定义变量,则输出10次10

  }

 

 

4.全局块作用域绑定

  当var被用于全局作用域时,它会创建一个新的全局变量作为全局对象(浏览器环境中的window对象)的属性,这意味着使用var和可能会无意中覆盖一个已经存在的全局属性;

  而使用let或者const,会在全局作用域下创建一个新的绑定,但该绑定不会添加为全局对象的属性,换句话说,用let或const不能覆盖全局变量,而只能遮蔽它;

  var  a = 1;

  let  b = 2;

  console.log(a);      // 1

  console.log(window.a);  //  1

  console.log(b);      // 2

  console.log(window.b);   // undefind

 

 

小结: 当前使用块级绑定的最佳实践是:默认使用const,只在确实需要改变变量的值时使用let。这样就可以在某种程度上实现代码的不可变,从而防止某些错误的产生。

    

posted @ 2019-12-26 21:49  小灬和灬尚  阅读(179)  评论(0编辑  收藏  举报