zoukankan      html  css  js  c++  java
  • JS中的var、let、const三者的区别

    ES5:var          ES6:let、const

    ES5中的作用域有---全局作用域、函数作用域
    ES6中新增了---块级作用域(块级作用域由{}包裹,if语句、for语句中的{}也属于块级作用域)

    • var

      1. 没有块级作用域的概念
      2. 有全局作用域、函数作用域的概念
      3. 不初始化值默认为undefined
      4. 存在变量提升
      5. 全局作用域用var声明的变量会挂载到window对象下
      6. 同一作用域中允许重复声明
    • let

      1. 有块级作用域的概念
      2. 不存在变量提升
      3. 暂时性死区
      4. 不存在全局作用域的概念
      5. 同一块作用域中不允许重复声明
    • const

      1. 与let特性一样,仅有2个差别
      2. 区别1——必须立即初始化,不能留到以后赋值
      3. 区别2——常量的值不能改变


    var关键字

    var-------------(没有块级作用域的概念)

    //Global Scope
    {
      var a = 10;
    }
    console.log(a);  //10
    

    上面代码中,在Global Scope(全局作用域)中,且在Block Scope(块级作用域){}中,a输出结果为10,由此可以看出var声明的变量不存在block scope的概念

    var-------------(有全局作用域、函数作用域的概念)

    //Global Scope
    var a = 10;
    function checkscope(){
        //Local Scope
        var b = 20;
        console.log(a);  //10
        console.log(b);  //20
    }
    checkscope();
    console.log(b);  //ReferenceError: b is not defined
    

    上面代码中,在Global Scope中用var声明了a,在checkscope函数中的Local Scope(本地作用域、函数作用域)中打印出了10,但是在Global Scope中打印的变量b报错了。

    var-------------(不初始化值默认为undefined)

    //Global Scope
    var a;
    console.log(a);  //undefined
    

    上面代码中,在Global Scope中用var声明了a,但没有初始化值,它的值默认为undefined,这里是undefinedundefined类型,而不是字符串。

    var-------------(存在变量提升)

    //Global Scope
    console.log(a);  //undefined
    var a = 10;
    
    checkscope();
    function checkscope(){
        //Local Scope
        console.log(a);  //undefined
        var a;
    }
    

    上面代码中,先打印了a,然后用var声明变量a。变量提升是因为JS需要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量。可以将这个过程形象地想象成所有的声明(变量)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。
    至于checkscope函数中的变量a为什么输出undefined,自己去看作用域链。

    var-------------(全局作用域用var声明的变量会挂载到window对象下)

    //Global Scope
    var a = 10;
    console.log(a);  //10
    console.log(window.a);  //10
    console.log(this.a);  //10
    

    上面代码中,打印出了3个10,访问awindow.a或是this.a都是等价的。举个例子:比如我要访问location对象,使用location可以访问,使用window.location也可以访问,只不过window对象可以省略不写,就像new Array()new window.Array()是等价的。

    var-------------(同一作用域中允许重复声明)

    //Global Scope
    var a = 10;
    var a = 20;
    console.log(a);  //20
    
    checkscope();
    function checkscope(){
        //Local Scope
        var b = 10;
        var b = 20;
        console.log(b);  //20
    }
    

    上面代码中,在Global Scope中声明了2次a,以最后一次声明有效,打印为20。同理,在Local Scope也是一样的。



    let关键字

    let-------------(有块级作用域的概念)

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

    上面代码中,打印a报错,说明存在Block Scope的概念。

    let-------------(不存在变量提升)

    {
      //Block Scope
      console.log(a);  //ReferenceError: Cannot access 'a' before initialization
      let a = 10;
    }
    

    上面代码中,打印a报错:无法在初始化之前访问。说明不存在变量提升。

    let-------------(暂时性死区)

    {
      //Block Scope
      console.log(a);  //ReferenceError: Cannot access 'a' before initialization
      let a = 20;
    }
    
    if (true) {
      //TDZ开始
      console.log(a);  //ReferenceError: Cannot access 'a' before initialization
    
      let a; //TDZ结束
      console.log(a);  //undefined
    
      a = 123;
      console.log(a);  //123
    }
    

    上面代码中,使用let声明的变量a,导致绑定这个块级作用域,所以在let声明变量前,打印的变量a报错。

    在用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

    简单的来说:使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

    其实上面不存在变量提升的例子中,其实也是暂时性死区,因为它有暂时性死区的概念,所以它压根就不存在变量提升了。

    let-------------(不存在全局作用域的概念)

    <script>
    var foo = 'foo';
    function bar(){}
    let a = 10;
    console.log(a);  //10
    console.log(window.a);  //undefined
    </script>
    

    图例-1

    上面代码中,打印变量a为10,但是打印window.aundefined,说明它不会挂在到window对象下,其实window对象是个顶层对象,他与Global不是一个东西,只不过在ES5中设计的时候,就把在Global中声明的变量(全局变量)自动的挂载到了window这个顶层对象里面了,所以我们在使用var声明全局变量的时候会自动把这个变量挂载到window对象里去。window对象与Global会互相挂钩。

    图例-1是在Firefox Developer Edition中的Debugger显示的。

    let-------------(同一块作用域中不允许重复声明)

    {
      //Block Scope
      let A;
      var A;  //SyntaxError: Identifier 'A' has already been declared
    }
    {
      //Block Scope
      var A;
      let A;  //SyntaxError: Identifier 'A' has already been declared
    }
    {
      //Block Scope
      let A;
      let A;  //SyntaxError: Identifier 'A' has already been declared
    }
    


    ##
    const关键字
    ### const-------------(必须立即初始化,不能留到以后赋值) ``` { //Block Scope const a; //SyntaxError: Missing initializer in const declaration } ``` 上面代码中,用`const`声明的变量`a`没有进行初始化,所以报错。
    ### const-------------(常量的值不能改变) ``` { //Block Scope const a = 10; a = 20; //TypeError: Assignment to constant variable } ``` 上面代码中,用`const`声明了变量`a`且初始化为10,然后试图修改`a`的值,报错。 `const`实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
  • 相关阅读:
    常见协议基础知识总结--FTP协议
    DG增量恢复
    DG备库无法接受主库归档日志之密码文件
    Oracle密码概要文件,密码过期时间180天修改为3天,相关用户密码是否过期
    ORA-15025 搭建DG环境,restore controlfile报错,提示oracle无法使用ASM存储
    Deinstall卸载RAC之Oracle软件及数据库+GI集群软件
    增加临时表空间组Oracle11g单实例
    安装12C小问题及pdb表空间配置
    判断子表外键约束参数类型
    创建small表空间size32G报错ORA-01144
  • 原文地址:https://www.cnblogs.com/liu-di/p/11889683.html
Copyright © 2011-2022 走看看