• 【ES6知识】简介、语法变化、解构赋值


    一、概述

    1.1 ECMAScript 简介

    ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发布。

    ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。

    1.2 ECMAScript 背景

    JavaScript 是大家所了解的语言名称,但是这个语言名称是商标( Oracle 公司注册的商标)。因此,JavaScript 的正式名称是 ECMAScript 。1996年11月,JavaScript 的创造者网景公司将 JS 提交给国际化标准组织 ECMA(European computer manufactures association,欧洲计算机制造联合会),希望这种语言能够成为国际标准,随后 ECMA 发布了规定浏览器脚本语言的标准,即 ECMAScript。这也有利于这门语言的开放和中立。

    1.3 ECMAScript 的历史

    ES6 是 ECMAScript 标准十余年来变动最大的一个版本,为其添加了许多新的语法特性。

    • 1997 年 ECMAScript 1.0 诞生。
    • 1998 年 6 月 ECMAScript 2.0 诞生,包含一些小的更改,用于同步独立的 ISO 国际标准。
    • 1999 年 12 月 ECMAScript 3.0诞生,它是一个巨大的成功,在业界得到了广泛的支持,它奠定了 JS 的基本语法,被其后版本完全继承。直到今天,我们一开始学习 JS ,其实就是在学 3.0 版的语法。
    • 2000 年的 ECMAScript 4.0 是当下 ES6 的前身,但由于这个版本太过激烈,对 ES 3 做了彻底升级,所以暂时被"和谐"了。
    • 2009 年 12 月,ECMAScript 5.0 版正式发布。ECMA 专家组预计 ECMAScript 的第五个版本会在 2013 年中期到 2018 年作为主流的开发标准。2011年6月,ES 5.1 版发布,并且成为 ISO 国际标准。
    • 2013 年,ES6 草案冻结,不再添加新的功能,新的功能将被放到 ES7 中;2015年6月, ES6 正式通过,成为国际标准。

    1.4 ES6 的目标与愿景

    以成为更好编写的开发语言为目标。

    可以适应更复杂的应用;实现代码库之间的共享;不断迭代维护新版本。

    1.5 学习路线图

    img

    1.6 环境搭建

    查看浏览器兼容:http://kangax.github.io/compat-table/es6/4

    支持ES6(ES2015)的浏览器:IE10+、Chrome、Firefox、移动端、NodeJS

    ES6语法编译、转换

    • 在线转换 通过 script[src] 引入 browser.js
    • 提前编译

    babel === browser.js

    二、语法变化

    2.1 let 与 const

    关键字 var 的问题

    • 可以重复声明

      var a = 10;
      var a = 20;
      console.log("a:",a);
      
      • 1
      • 2
      • 3
    • 无法限制修改

      var b = 10;
      b = 20;
      console.log("b:",b);
      
      • 1
      • 2
      • 3
    • 没有块级作用域(存在变量提升)

      {
          var a = 10;
      }
      ​
      if(true){
          var b = 10;
      }
      console.log("a:",a,"b:",b)
      ​
      for(var i = 0; i < 10; i++){
          console.log("i:",i);
      }
      console.log("i:",i);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    2.2 解构赋值

    • 左右两边结构必须一样

      // 错误示例
      let [a, b] = {a:1, b:2};
      // 类型错误 TypeError: {(intermediate value)(intermediate value)} is not iterable
      
      • 1
      • 2
      • 3
    • 右边必须是一个合法值

      // 错误示例
      let {a, b} = {12, 5}; //{12, 5} 啥也不是
      // 语法错误 SyntaxError: Unexpected token ','
      
      • 1
      • 2
      • 3
    • 声明和赋值不能分开(必须在一句话中完成)

      // 错误示例
      let [a,b];
      [a, b] = [1, 2];
      // SyntaxError: Missing initializer in destructuring declaration
      // 语法错误 在解构声明中缺少初始化式
      
      • 1
      • 2
      • 3
      • 4
      • 5

    2.3 Symbol

    ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名,这样就从根本上防止属性名的冲突。

    Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。基本上可以说,它是一种类似于字符串的数据类型。

    Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

    let s1 = Symbol('foo');
    let s2 = Symbol('bar');
    ​
    s1 // Symbol(foo)
    s2 // Symbol(bar)
    ​
    s1.toString() // "Symbol(foo)"
    s2.toString() // "Symbol(bar)"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面代码中,s1s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。

    ES2019 提供了一个实例属性description,直接返回 Symbol 的描述。

    const sym = Symbol('foo');
    sym.description // "foo"
    
    • 1
    • 2

    由于每一个 Symbol 的值都是不相等的,所以 Symbol 作为对象的属性名,可以保证属性不重名。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

    let mySymbol = Symbol("foo");
    ​
    // 第一种写法
    let a = {};
    a[mySymbol] = 'Hello!';
    ​
    // 第二种写法
    let a = {
      [mySymbol]: 'Hello!'
    };
    ​
    // 第三种写法
    let a = {};
    Object.defineProperty(a, mySymbol, { value: 'Hello!' });
    ​
    // 以上写法都得到同样结果
    a[mySymbol] // "Hello!"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意,Symbol 值作为对象属性名时,不能用点运算符

    const mySymbol = Symbol();
    const a = {};
    ​
    a.mySymbol = 'Hello!';//这里mySymbol作为a的属性进行赋值
    a[mySymbol] // undefined
    a['mySymbol'] // "Hello!"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面代码中,因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值,导致a的属性名实际上是一个字符串,而不是一个 Symbol 值。同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。

    Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols()Reflect.ownKeys() 取到。

    let syObject = {};
    syObject[sy] = "kk";
    console.log(syObject);
     
    for (let i in syObject) {
      console.log(i);
    }    // 无输出
     
    Object.keys(syObject);                     // []
    Object.getOwnPropertySymbols(syObject);    // [Symbol(key1)]
    Reflect.ownKeys(syObject);                 // [Symbol(key1)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Symbol 值作为属性名时,该属性是公有属性不是私有属性,可以在类的外部访问。

    Symbol.for() 类似单例模式,首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值,如果有即返回该 Symbol 值,若没有则新建并返回一个以该字符串参数为名称的 Symbol 值,并登记在全局环境中供搜索。

    let yellow = Symbol("Yellow");
    let yellow1 = Symbol.for("Yellow");
    yellow === yellow1;      // false
     
    let yellow2 = Symbol.for("Yellow");
    yellow1 === yellow2;     // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ,用来检测该字符串参数作为名称的 Symbol 值是否已被登记。

    let s1 = Symbol.for("foo");
    Symbol.keyFor(s1) // "foo"
    ​
    let s2 = Symbol("foo");
    Symbol.keyFor(s2) // undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面代码中,变量s2属于未登记的 Symbol 值,所以返回undefined

    注意,Symbol.for()为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。

  • 相关阅读:
    Spring Boot Admin 介绍及使用
    MacBook/MacOS如何更新到指定的版本
    Linux下内存检测利器Valgrind之Memcheck工具详解
    JAVA电费管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
    临界区、临界资源、共享资源、临界调度原则
    iOS TestFlight 使用详解
    Day804.原型模式与享元模式 -Java 性能调优实战
    Pytorch CPU版本安装教程
    六级易混词整理
    【LeetCode-面试经典150题-day25】
  • 原文地址:https://blog.csdn.net/qq_39335404/article/details/132824843