【JavaScript】let(const)与var 关键字


前言

letconstES6新增特性,都可生成块级作用域(是指声明在花括号内的变量只在该区域内有效)。let用来声明变量,const用来声明常量(不可修改变量值,数组和对象除外);两者处了在用途有区分外,其他特性一致,如无变量提升、TDZ等。
let(const)的出现可以解决的问题:

  • 解决ES5var变量出现的变量提升
  • 降低闭包使用出错的概率;
  • 解决使用计数的for循环变量可能会导致的数据泄露
  • ES5只有全局作用域和函数作用域(对应var声明的全局变量和局部变量时),没有块级作用域(ES6{}中的代码块)。同理只能在顶层作用域window中和函数中声明函数,不能在块级作用域中声明函数;

一、letconst的特点:

  1. letconst关键词声明的变量不具备变量提升的特效、存在暂时性的死区、只能在声明的位置后使用,同一块级作用域中不能反复声明同一变量名(子块级可以重复声明父块级变量),而var变量可以重复声明;

  2. letconst声明只在最靠近的一个块(花括号内)中有效;

  3. 使用const声明常量时候大写,const在声明时必须赋值;

  4. const声明的变量值并不是不能变的,而是变量指向的内存地址是不能变的,对于数值、字符串等简单类型的数据,值就保存在变量指向的内存地址上,因此等同于常量;但对于符合类型的数据(如数组和对象),变量指向的内存地址是一个指引,数据结构是否可变就不能控制了,所以将对象声明为常量必须非常小心;

    const newArr=[23,43,22,66];
    newArr[0]=888;
    console.log(newArr); //[888, 43, 22, 66]```
    

二、let(const)与let的区别

  1. 作用域
  • 通过var关键字声明的变量无块作用域,在块{ }内声明的变量,存在变量提升,可以从块之外进行访问;

  • 通过let关键字声明的变量有块作用域,在块{ }内声明的变量无法从块外访问。

    ```javascript
    function varTest() {
      var x = 1;
      {
        var x = 2;  // same variable!
        console.log(x);  // 2
      }
      console.log(x);  // 2
    }
    ---------------------------------------
    function letTest() {
      let x = 1;
      {
        let x = 2;  // different variable
        console.log(x);  // 2
      }
      console.log(x);  // 1
    }
    ```
    
  1. 变量提升 && 暂时性死区
  • 通过var 声明的变量存在变量提升,并被初始化为undefined

  • 通过 let声明的变量没有变量提升,而且要求必须 等let声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError错误;在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

    {
        console.log(aicoder);    // undefined 因为有变量提升
        var aicoder = 'aicoder.com';
    }
        ---------------------------------------------------------------
    {
        console.log(aicoder);    // Uncaught ReferenceError ...
        let aicoder = 'aicoder.com';
        // 这里就可以安全使用aicoder  
    }
    
  1. 重复声明
  • var声明的变量可以重复声明;

  • let声明的变量不允许在相同作用域内重复声明, 所以也不能在有参函数声明中重复声明函数参数,否则会报错

    {
        var a = 0;
        console.log(a); // 0
        var a = 'sss';
        console.log(a); // sss
    }
    {
       let a = 0;
       let a = 'sss';
       // Uncaught SyntaxError: Identifier 'a' has already been declared
    }
    

注:
1) 在相同的作用域,或在相同的块中:

  • 仅允许通过var重新声明var变量;
  • 通过let重新声明一个var变量是不允许的;
  • 通过let重新声明一个let变量是不允许的;
  • 通过var重新声明一个let变量是不允许的。

​2) 在不同的作用域或块中:通过 letvar重新声明变量是允许的。
​3) 不能在函数内声明参数。

  1. 生成window对象
  • 通过 var 关键词定义的全局变量属于 window 对象;
  • 通过 let 关键词定义的全局变量不属于 window 对象。
   var x = 'global';
   let y = 'global';
   console.log(this.x); // "global"
   console.log(this.y); // undefined

注:在ES5中顶层对象(在浏览器指的是window对象),顶层对象属性和全局变量是等价的。属性也可以动态创建变量,顶层对象的属性可以被随处读写不利于模块化编程;

​ 而在ES6中,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值