ES6定义(声明)变量

定义(声明)变量

  • let命令

    1. 基本用法
       let用来声明变量,用法类似于var,但是let声明的变量,只有在let命令所在的代码块内有效。

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

       for循环的计数器 使用let不会有变量提升引起的泄露

      for(let 1=0;i<10;i++){
          //...
      }
      
      console.log(i);//ReferenceError:i is not defined
      //变量i只在for循环体内有效,在循环体外引用就会报错。
      

       注意:在for循环中,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

      for(let i =0;i<3;i++){
          let i='abc';
          console.log(i);
      }
      //结果 3此abc
      abc
      abc
      abc
      说明循环内部的变量i与循环变量i不在同一个作用域。
      
    2. 不存在变量提升
       var命令存在变量提升的现象,即变量可以在声明之前使用,值为undefined。
      let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

      //var 的情况
      console.log(foo);//输出undefined    
      var foo=2;
      ----变量提升后----
      var foo;
      console.log(foo);
      foo=2;
      //let的情况
      console.log(bar);//输出ReferenceError
      let bar=2;
      

      上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。
      变量bar用let命令声明,不存在变量提升。这表示在声明他之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

    3. 暂时性死区
       只要在块级作用域内用let声明和外层同名的变量,它所声明的变量就绑定(binding)这个区域,不再受外部的影响。

       var tmp =123;
       if(true){
           tmp='abc';
           let tmp;    
           console.log(tmp);//Uncaught ReferenceError: tmp is not defined
       }
       /*
           上面代码中,tmp首先为全局变量,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量之前,对tmp赋值会报错。
        */
      

       ES6规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错,这在语法上称为“暂时性死区”(temporal dead zone,简称TDZ)
      例:

        tmp='abc';//ReferenceError
        console.log(tmp);//ReferenceError
        
        let tmp;//TD结束
        console.log(tmp);//undefined
      
        tmp=123;  
        console.log(tmp);//123            
        //总之在let命令声明变量之前,都属于变量的暂时性死区      
      
    4. 不允许重复声明变量
       let不允许在相同作用域内,重复声明同一个人变量。

      {
          let a=10;
          var a=1;//报错
      }
      {
          let b=10;
          let b=1;//报错
      }   
      

       也不能在函数内部重新声明参数

          function f(a){
              let a;//报错
              if(true){
                  let a;//不会报错 
              }
          }        
      
  • const命令

    1. const与let的用法基本一致,let有的特性const也有;区别在于const声明一个只读的常量,一旦声明,常量的值就不能改变。
      如:
        const PI =3.1415;
        PI =3; 
        // Uncaught TypeError: Assignment to constant variable.  
    

     补充:const声明的变量不能改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

        const foo;
        //Uncaught SyntaxError: Missing initializer in const declaration
    
    1. const本质
       const实质上保证的,并不是变量的值不改动,而是变量指向的那个内存地址所保存的数据不得改动。
       对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
       但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针式固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。
      例:
       const foo ={};
       foo.prop=123;//为foo添加一个属性可以成功
       console.log(foo);//{prop: 123}
      
       foo ={};//将foo指向另一个对象,报错
       //Uncaught TypeError: Assignment to constant variable.
      
        const a=[];
        a.push('Hello');//可执行
        a.length=0;//可执行
        a=['Dave'];//Uncaught TypeError: Assignment to constant variable.
      
  • 顶层对象的属性

    顶层对象,在浏览器环境指的式window对象,在Node指的是global对象(全局对象)。

    • 在ES5中,顶层对象的属性与全局变量是等价的。
      如:
      window.a = 1;
      console.log(a);//1
      a = 2;
      console.log(window.a);//2
    
    • ES6规定:
      • var和function声明的全局变量,依旧是顶层对象的属性
      • let和const、class声明的全局变量不属于顶层对象的属性
        如:
      var a= 1;
      console.log(window.a);//1
      let b=1;
      console.log(window.b);//undefined
    
  • global对象

  1. JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。
    全局对象不是任何对象的属性,所以它没有名称。
  2. global对象在不同的环境中实现也是不一样的
    如:
    • 在浏览器里,就是window
    • 在Node里,就是global
  3. 关于this变量
    • 全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块。
    • 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是严格模式下,这时this会返回undefined。

猜你喜欢

转载自blog.csdn.net/YCJ_xiyang/article/details/82798243