• ES6新语法之---块作用域let/const(2)


    前言:

      ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了,这节学习掌握ES6中的let/const。

      1.JavaScript中的作用域

        1>函数作用域

          JavaScript中变量作用域的基本单元一直是函数(function)

    <script>
        // 此处的a在{}中声明赋值
        if (true) {
            var a = 3
            console.log(a)  //打印3
        }
        console.log(a)  //打印3
    
        // JavaScript中函数是变量作用域的基本单元
        function fn2() {
            var b = "5";
            console.log(b); //打印5
        }
        fn2();
        console.log(b);//会报错 Uncaught ReferenceError: b is not defined
    </script>

         2>"真假"块作用域

          除了JavaScript外的很多编程语言都支持块作用域(比如:项目中使用的java)

         举例:"假"块作用域

          我们在for循环的头部定义了变量i,通常是只想在for循环内部的上下文中使用i,但最后我们却可以在for之外访问到它,这样就造成了i对整个函数作用域的污染。

     for (var i = 0; i < 10; i++) {
            console.log(i)
     }
     console.log(i)  //打印出10

        举例:"真"块作用域

          JavaScript的ES3规范中规定try/catch中的catch分句会创建一个块作用域,其中声明的变量仅在catch内部有效。

    <script>
        try {
            undefined() //执行一个非法操作来强制制造一个异常
        } catch (error) {
            console.log(err)    //能够正常执行,err仅在catch的作用域中有效
        }
        console.log()   //ReferenceError: err is not defined
    </script>

      

      2.ES6中的let

        ES6引入了新的let关键字,提供le除var以外的另一种变量声明方式。let关键字可以将变量绑定到所在的任意作用域中。

        1>let声明的变量只在当前代码块有效

    {
        let a = 10;
        var b = 1;
    }
    console.log(a) // ReferenceError: a is not defined
    console.log(b) // 1

        2>let在for循环中的使用

    let funcs = [];
    for (let i = 0; i< 5; i++) {
        funcs.push(function () {
            console.log(i)
        });
    }
    funcs[3]();    //打印结果是3

        上例中,for循环头部的let i 不只为for循环本身声明了一个i,而是为循环的每一次迭代都声明了一个新的变量i,这样数组成员中变量i都是独立唯一的。

    var funcs = [];
    // 此处用var声明了全局变量i
    for (var i = 0; i< 5; i++) {
        funcs.push(function () {
            //此处的i指向的就是全局变量i
            console.log(i)
        });
    }
    funcs[3](); 5//最后数组成员中的i指向都是同一个全局变量i

        上例中,for循环头部的var i 声明了一个全局变量,数组成员中变量i指向的都是同一个全局变量

        3>不存在变量提升

          var声明的变量会发生变量提升现象,既在变量声明之前可以对变量进行访问,结果是'undefined'

          let声明归属于块作用域,但是直到在块中出现才会初始化。

    {
          console.log(a);   //undefined
          console.log(b);   //ReferenceError
        
          var a;
          var b;
      }

          在let声明/初始化之前访问let声明的变量会导致错误,这个错误严格叫做临时死亡区(Temporal Dead Zone, TDZ)

          对于TDZ值和未声明值,typeof结果是不同的,举例:

     {
            if (typeof a === "undefined") { //条件成立,未声明变量默认为undefined
                console.log("cool");
            }
    
            if (typeof b === "undefined") { //ReferenceError
                //...
            }
            let b;
        }

          建议:let声明的变量最好置于当前作用域开始的位置。    

        4>不允许重复声明

          let不允许在相同的作用域中声明同一个变量,也不允许在函数内部重新声明其参数

          举例:同一个作用域

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

          举例:声明函数参数

        function func(arg) {
          let arg; // 报错
        }
    
        function func(arg) {
           {
            let arg; // 不报错
           }
        }

      3.ES6中的const

        const声明一个只读的常量。一旦声明,常量的值就不能改变。

            {
                const a = 2;
                console.log(a);
                //const声明的常量,值不允许再改变
                a = 3;  //TypeError
            }    

        变量a的值在声明时必须显示初始化,而且之后就不允许改变

        注意:

          常量不是对这个值的限制,而是对赋值的那个变量的限制

        举例:值为复杂类型

            {
                const a = [1, 2, 3];    //此时a指向的是[1, 2, 3]的地址
                a.push(4);      //[1, 2, 3]内容发生了改变,但是对象地址本身没有改变。
                console.log(a);
                //const声明的常量,值不允许再改变
                a = 3;  //TypeError     //变量a重新赋值就会报错
            }        

        上例中,const限制是a变量本省,而非[1, 2, 3]这个数组对象。

        注意:

          1.const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了

          2.const同样不支持变量提升

          3.const同样存在临时死亡区(TDZ)

  • 相关阅读:
    进程与线程(二) java进程的内存模型
    进程学习(一) 进程的地址空间
    在一个数组中除两个数字只出现1次外,其它数字都出现了2次
    倒水问题
    leecode 树是否是平衡树 java
    Max Sum
    Encoding
    海阔天空-
    Binomial Showdown
    Square
  • 原文地址:https://www.cnblogs.com/diweikang/p/8949717.html
Copyright © 2020-2023  润新知