zoukankan      html  css  js  c++  java
  • let和const的理解以及let,const,var的区别

     let基本用法
        {
            let a = 1
            var b = 2
        }
        console.log(a)    //Uncaught ReferenceError: a is not defined 未捕获引用错误:a是未定义
        console.log(b)     //2
        概念:在ES6中凡是{}包裹的代码都是块级作用域,凡是在块级作用域中用let const声明的变量都在有一个暂时性死区
        代码块内有效 let 是在代码块内有效,var 是在全局范围内有效
     
        不能重复声明

        let 只能声明一次, var 可以声明多次
      {
            let a = 1;
            let a = 2;
            var b = 3;
            var b = 4;
        }
        console.log(a)     //Uncaught SyntaxError: Identifier 'a' has already been declared 未捕获的语法错误:已声明标识符“a”
        console.log(b)     //4
     
     for 循环计数器很适合用 let
        for (var i = 0; i < 10; i++) {
            setTimeout(function () {
                console.log(i);     //10次10
            })
        }
    
        for (let j = 0; j < 10; j++) {
            setTimeout(function () {
                console.log(j);   //0123456789
            })
        }
        另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
        for (var i = 0; i < 3; i++) {
            var i = 'abc';
            console.log(i);     //输出一次abc
        }
    
    
        for (let j = 0; j < 3; j++) {
            let j = 'abc';
            console.log(j);     //输出三次abc
        }
       这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

        
    不存在变量提升

      var 的情况   
        console.log(b); // 输出undefined
        var b = 2;
        let 的情况  
        console.log(a);    // 报错Uncaught ReferenceError: Cannot access 'a' before initialization未捕获的引用错误:无法在初始化之前访问“a”
        let a = 2;

        变量 b 用 var 声明存在变量提升,所以当脚本开始运行的时候,b 已经存在了,但是还没有赋值,所以会输出 undefined。

        变量 a 用 let 声明不存在变量提升,在声明变量 a 之前,a 不存在,所以会报错。
     
     暂时性死区
        只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
        var a = 123;
    
        if (true) {
          //console.log(a) //Uncaught ReferenceError: Cannot access 'a' before initialization   未捕获的引用错误:无法在初始化之前访问“a”
          a = 'abc'; 
          let a;
          //console.log(a)
        }
        上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
        ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
        总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
     
     
    “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
        typeof x; // Uncaught ReferenceError: Cannot access 'x' before initialization  未捕获的引用错误:无法在初始化之前访问“x”
    
        let x;
        console.log(typeof x)

      上面代码中,变量x使用let命令声明,所以在声明之前,都属于x的“死区”,只要用到该变量就会报错。因此,typeof运行时就会抛出一个ReferenceError。

        作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。
        
        typeof y
        console.log(typeof y)   //undefined
        上面代码中,y是一个不存在的变量名,结果返回“undefined”。所以,在没有let之前,typeof运算符是百分之百安全的,永远不会报错。现在这一点不成立了。
        这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。
     
        有些“死区”比较隐蔽,不太容易发现。
         function bar(x = y, y = 2) {
          return [x, y];
        }
    
        console.log(bar())   // 报错Uncaught ReferenceError: Cannot access 'y' before initialization 未捕获的引用错误:无法在初始化之前访问“y”
    
        function bar(x = 2, y = x) {
          return [x, y];
        }
    
        console.log(bar())// [2, 2]
    上面代码中,调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了。
     
    另外,下面的代码也会报错,与var的行为不同。    
        var x = x;
        console.log(x)    // 不报错
      
    
        let y = y;
        console.log(y)  // ReferenceError: y is not defined y是未定义的
        
        上面代码报错,也是因为暂时性死区。使用let声明变量时,只要变量在还没有声明完成前使用,就会报错。上面这行就属于这个情况,在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。

        ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。

        总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
     
        const基本用法
        const声明一个只读的常量。一旦声明,常量的值就不能改变。
        const a = 123;
        a = 3;
        console.log(a)    //Uncaught TypeError: Assignment to constant variable.    上面代码表明 未捕获类型错误:分配给常量变量。

        const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
        const a;
        console.log(a)  // SyntaxError: Missing initializer in const declaration   const声明中缺少初始值设定项
     
        上面代码表示,const声明中缺少初始值设定项 ,对于const来说,只声明不赋值,就会报错。

        const的作用域与let命令相同:只在声明所在的块级作用域内有效。
        if (true) {
          const a = 5;
        }
        console.log(a)    //Uncaught ReferenceError: a is not defined    a是未定义的
        const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

        
        if (true) {
          console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization 未捕获的引用错误:无法在初始化之前访问“a”
          const a = 5;
        }
        上面代码在常量a声明之前就调用,结果报错。

        const声明的常量,也与let一样不可重复声明。

        
        const foo = {};

        为 foo 添加一个属性,可以成功
        foo.prop = 123;
        foo.prop // 123

        将 foo 指向另一个对象,就会报错
        
        上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。
        不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

        下面是另一个例子。

        const a = [];
        a.push('Hello'); // 可执行
        a.length = 0;    // 可执行
        a = ['Dave'];    // 报错Uncaught TypeError: Assignment to constant variable.   未捕获类型错误:分配给常量变量。
        上面代码中,常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。
      
     
      var,const,let的区别
        var
          支持变量声明与解析
          不支持块级作用域
          允许重复声明
        let
          不支持变量声明与解析
          支持块级作用域
          不允许重复声明
          用let声明的变量或者方法只会在代码块中有效
        const
          不支持变量声明与解析
          支持块级作用域
          不允许重复声明,声明变量,一旦确定不允许被修改
          声明变量必须赋值,不能跟var一样声明后再定义
     

     
     
     
     
  • 相关阅读:
    Java中如何动态创建接口的实现
    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
    MyBatis中的@Mapper注解及配套注解使用详解(上)
    SpringMVC-DispatcherServlet工作流程及web.xml配置
    SpringMVC-DispatcherServlet配置(Spring-servlet.xml)
    Spring MVC 配置文件dispatcher-servlet.xml 文件详解
    python3 UnicodeEncodeError: 'gbk' codec can't encode character 'xa0' in position 30: illegal multibyte sequence
    python3之日期和时间(转载)
    python3 操作sqlSever
    python 抓取alexa数据
  • 原文地址:https://www.cnblogs.com/shy0113/p/11862876.html
Copyright © 2011-2022 走看看