zoukankan      html  css  js  c++  java
  • 关于ES6的let、const那些事儿

    Babel 转码器

    Babel是广泛使用的一个ES6转换器,将ES6代码转换成ES5代码,从而实现在老版本的浏览器执行。

    let和const命令

    let所声明的变量只在let命令所在的代码块内是有效的。

    {
      let a = 10;
      var b = 1;
    }
    
    a // 10
    b // index.html:16 Uncaught ReferenceError: b is not defined
    

    通过let给出了变量的作用域问题,在我们通常的for循环使用比较方便

            var a = [];
            for (var i = 0; i < 10; i++) {
                a[i] = function () {
                    console.log(i);
                };
            }
    
            for (let i = 0; i < 10; i++) {
                a[i] = function () {
                    console.log(i);
                };
            }
        a[6]()
    //当用var声明变量的时候,发现,在输出框内,输出的值是10,也是就说var定义的i是全局的变量,
    //所以在全局内只有一个i,当后续的值不断写入之后,不断地覆盖之前的值
    //如果使用let定义变量的话,由于作用域是在块级,也就是说,每一次循环都是一个新的变量,所以我们可以输出6
    

    变量提升

    在用var定义变量时,我们可以在声明之前就使用变量,值为underfined,也就是变量提升
    在使用let定义变量时,如果变量没有定义或者说,在变量定义之前就使用变量的话,会报错Uncaught ReferenceError的

            console.log(a);     //undefined
            var a = 10;
    
            console.log(b);     //Uncaught ReferenceError
            let b = 5;
    

    暂时性死区

    只要块级作用域存在let命令,所声明的变量就绑定了这个区域,不再受外部的影响。

    var tmp = 123;
    
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    

    报错!也就是首先存在全局变量tmp,在块级作用域中,对tmp的赋值在声明变量之前,导致let声明的tmp绑定了这个块级作用域
    ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。
    凡是在声明之前就使用这些变量,就会报错。
    在let声明变量之前都是不可以使用的,在语法称作暂时性死区

    var tmp = 123;
    if (true) {
        let tmp;
        tmp = 'abc';
        console.log(tmp);   //abc      
    }
    console.log(tmp);      //123
    

    在这种情况下对变量首先进行声明,在之后的使用中也就不会报错了。

    if (true) {
      // TDZ开始
      tmp = 'abc'; // ReferenceError
      console.log(tmp); // ReferenceError
    
      let tmp; // TDZ结束。在let声明之前,tmp都是属于死区
      console.log(tmp); // undefined
    
      tmp = 123;
      console.log(tmp); // 123
    }
    

    “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。在使用typeof的时候报ReferenceError错误,但是没有声明的变量报underfined错误

    function bar(x = y, y = 2) {
      return [x, y];
    }
    
    bar(); // 报错,在将y赋值给x的时候,y是没有被声明的,同样在使用let x=x 的时候,也是会报错的,将x赋值给x,但是后面的x并没有被定义
    

    不允许重复声明

    let不允许在相同的作用域内,重复声明同一个变量

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

    同时,在函数内部重新声明参数也是不可以的

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

    块级作用域

    在ES5中,只有全局作用域和函数作用域,没有块级作用域
    块级作用域实现了块级作用域之间的一个嵌套,每一个块级对应都是他的一个作用域,内外层的变量就可以不受影响

    块级作用域和函数声明
    在ES5中,函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明,但是浏览器没有遵循这个规定,也就是说,在浏览器中是不会报错的
    在ES6中,块级作用域必须要有大括号,否则mJavaScript引擎就认为不存在块级作用域。

    const命令

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

    const PI = 3.1415;
    PI // 3.1415
    
    PI = 3;
    // TypeError: Assignment to constant variable.
    

    只声明不在赋值会报错

    const foo;
    // SyntaxError: Missing initializer in const declaration
    

    const的作用域与let命令相同:只在声明所在的块级作用域内有效。

    if (true) {
      const MAX = 5;
    }
    
    MAX // Uncaught ReferenceError: MAX is not defined
    

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

  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/Indomite/p/13265424.html
Copyright © 2011-2022 走看看