ES6语法详解

ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。

ES6 实际上是一个泛指,泛指 ES2015 及后续的版本。

目录

1. let 关键字和 const 关键字

let 关键字

const 关键字

2. 解构赋值

数组解构赋值

对象解构赋值

解构赋值用于传参

3. 字符串新增特性

模板字符串

字符串实例新增方法

4. 数值新增特性

新增二进制和八进制表示方法

Number 构造函数本身新增方法和属性

安全整数

5. Math 新增方法

ES3 属性方法

ES6 新增方法

6. 指数运算符

7. 新增原始数据类型 BigInt

8. 函数新增特性

函数参数的默认值

rest 参数

箭头函数

箭头函数的特点

函数参数尾逗号(ES2017)

9. 数组的新特性

扩展运算符

扩展运算符的应用场景

rest 元素

Array 构造函数本身新增的方法

Array 实例新增方法

10. 对象新特性

对象声明时候的简写

声明对象时方法的简写

属性名表达式

super 关键字

对象的扩展运算符

对象的扩展运算符用于对象解构赋值

Object 构造函数本身新增的方法

Object 实例新增的属性

11. Class 语法

使用 Class 定义类

类的语法特性

类中定义构造器方法

静态方法

访问器属性

实现继承

方法和属性的重写

super 关键字

继承系统类(内置的构造函数)

12. 新增元素数据类型 Symbol

13. 新增数据类型 Set 和 Map

Set 数据类型

WeakSet 数据类型

Map 数据类型

WeakMap 数据类型

14. Iterator 遍历器对象和可遍历对象

Iterator 遍历器对象

Iterable 可遍历对象

15. 生成器 Generator

定义

如何定义

yield 关键字

return 可以终止生成器遍历

利用生成器对象部署 Iterator 接口

16. 模块(Module)

定义模块

模块导入

17. 新增的运算符(ES2020)

可选链运算符 ?.

空值合并运算符 ??


1. let 关键字和 const 关键字

let 关键字
  • 作用:声明变量,用来代替 varlet 声明的变量具备变量的基本特征。

  • 语法let 变量名 = 值;

  • 特点

    • let 声明的变量不能重复声明。

    • let 声明的变量不会变量提升。

    • let 声明的变量不会再作为顶层全局的属性。

    • let 声明的变量在全局作用域和局部作用域的基础上新增了块级作用域。

块级作用域

  • 产生块级作用域的语法:

    • {} 语法

      {
          let x = 1;
          console.log(x); // 1
      }
      console.log(x); // ReferenceError: x is not defined
    • for / while 循环结构

      for (let i = 0; i < 5; i++) {
          console.log(i); // 0, 1, 2, 3, 4
      }
      console.log(i); // ReferenceError: i is not defined
    • if / else / switch 分支结构

      if (true) {
          let y = 2;
          console.log(y); // 2
      }
      console.log(y); // ReferenceError: y is not defined
    • try / catch

      try {
          let z = 3;
          console.log(z); // 3
      } catch (error) {
          console.log(error);
      }
      console.log(z); // ReferenceError: z is not defined
const 关键字
  • 作用:用于定义常量,常量的特点是值不能修改。为了与变量区分,一般常量名一般采用全部大写(潜规则)。

  • 特点

    • const 声明的常量,不能重新赋值也不能重新声明。

    • 全局变量不会作为顶层全局对象的属性值。

    • 变量不会提升。

    • 常量在全局作用域和局部作用域的基础上新增了块级作用域。

示例

const PI = 3.14159;
console.log(PI); // 3.14159
PI = 3.14; // TypeError: Assignment to constant variable.

const obj = { name: '张三' };
console.log(obj.name); // 张三
obj.name = '李四'; // 常量对象的属性可以修改
console.log(obj.name); // 李四

2. 解构赋值

数组解构赋值
  • 变量声明赋值

    let [a, b, c] = [1, 2, 3];
    console.log(a, b, c); // 1, 2, 3
  • 变量赋值

    [a, b, c] = [5, 6, 7];
    console.log(a, b, c); // 5, 6, 7
  • 解构赋值可以有默认值

    let [d, e, f = 300] = [433, 45];
    console.log(d, e, f); // 433, 45, 300
  • 数组解构可以是直接量也可以是变量

    let arr = [5, 6, 4, 3];
    let [aa, bb, cc] = arr;
    console.log(aa, bb, cc); // 5, 6, 4

注意

数组解构赋值本质是按照索引进行解构的,等号右边必须是数组或者伪数组(具有索引结构的),否则报错。

对象解构赋值
  • 按照属性名进行匹配

    let { name: username, age: userage } = { name: 'anni', age: 100 };
    console.log(username, userage); // anni, 100
  • 属性名和变量名相同则可以简写

    let { a, b } = { a: 55, b: 'anni' };
    console.log(a, b); // 55, anni
  • 变量名可以有默认值

    let { c, d = 100 } = { c: 89 };
    console.log(c, d); // 89, 100

注意

  1. 一切皆对象,一切都可以作为对象解构赋值(除了 nullundefined)。

  2. 对象解构赋值不需要按照索引,只要有属性就可以。

解构赋值用于传参
  • 数组的解构赋值

    function giao([a, b]) {
        console.log(a + b);
    }
    giao([100, 200]); // 300
  • 对象解构赋值

    function woligiao({ name, age, address }) {
        console.log(name, age, address);
    }
    woligiao({ name: 'anni', age: 99, address: '上海' });

3. 字符串新增特性

模板字符串
  • 定义:使用反引号声明的字符串,称为模板字符串。模板字符串适合内容较多,且需要嵌套很多变量的字符串。

  • 示例

    let [msg1, msg2] = ['are you ok', 'i am fine'];
    let html = `
        <ul>
            <li>${msg1}</li>
            <li>${msg2}</li>
            <li>${100 + 200}</li>
        </ul>
    `;
    console.log(html);
  • 特性

    • 在模板字符串中换行会作为字符串内容。

    • 模板字符串可以使用 ${} 嵌入变量,表达式都可以嵌入到模板字符串中。

    • 其他特性与单双引号字符串一致。

字符串实例新增方法
  • ES3 方法

    • indexOf():返回参数在字符串中的位置。

    • lastIndexOf():返回参数在字符串中最后一次出现的位置。

    • toUpperCase():将字符串转换为大写。

    • toLowerCase():将字符串转换为小写。

    • slice():返回字符串的子字符串。

    • substring():返回字符串的子字符串。

    • substr():返回字符串的子字符串。

    • split():将字符串分割为数组。

    • charCodeAt():返回指定位置的字符的 Unicode 编码。

  • ES5 方法

    • trim():去除字符串两边的空格,全是空格的字符串会转换为空字符串。

  • ES6+ 方法

    • repeat():字符串重复。

    • includes():判断字符串中是否包含某个值,返回布尔值;第二个参数可以指定查找开始的位置。

    • startsWith():判断字符串是否以某个值开头,返回布尔值;第二个参数指定开始查找的位置。

    • endsWith():判断字符串是否以某个值结束,返回布尔值;第二个参数指定字符串查找的长度。

    • padStart():将字符串补充到指定的长度,在前面添加,第一个参数指定总长度,第二个参数指定填充内容(ES2017)。

    • padEnd():将指定字符串补充到指定长度,将填充内容添加到后面,第一个参数是指定总长度,第二个参数指定填充内容(ES2017)。

    • trimStart():删除字符串左边的空格(ES2019)。

    • trimEnd():删除字符串右边的空格(ES2019)。

4. 数值新增特性

新增二进制和八进制表示方法
  • 示例

    let num1 = 0b101; // 二进制表示方法
    let num2 = 0o101; // 八进制表示方法
    console.log(num1); // 5
    console.log(num2); // 65
Number 构造函数本身新增方法和属性
  • ES3 属性

    • Number.MAX_VALUE

    • Number.MIN_VALUE

  • ES6 属性和方法

    • Number.isNaN():同全局属性 isNaN()

    • Number.isFinite():同全局函数 isFinite()

    • Number.parseInt():同全局函数 parseInt()

    • Number.parseFloat():同全局函数 parseFloat()

    • Number.isInteger():判断是否是整数,返回布尔值。

    • Number.isSafeInteger():判断是否是安全整数。

    • Number.MAX_SAFE_INTEGER:返回最大安全整数。

    • Number.MIN_SAFE_INTEGER:返回最小安全整数。

    • Number.EPSILON:返回 JS 的最小精度。

安全整数
  • 定义:在 -2^532^53 之间的整数称之为安全整数,不存在计算精度问题。超出该范围的数字计算存在精度问题。

5. Math 新增方法

ES3 属性方法
  • Math.PI

  • Math.abs()

  • Math.sqrt()

  • Math.pow()

  • Math.round()

  • Math.floor()

  • Math.ceil()

  • Math.random()

  • Math.max()

  • Math.min()

ES6 新增方法
  • Math.trunc():截取数字的整数部分,类似于 parseInt()

  • Math.sign():参数是正数返回 1,参数是负数返回 -1,参数等于 0 返回 0,参数是 NaN 返回 NaN

  • Math.hypot():求所有参数的平方和的平方根。

6. 指数运算符

  • 示例

    console.log(3 ** 3); // 27

7. 新增原始数据类型 BigInt

  • 定义:如果要进行计算的数字超过安全整数的范围,还想保证精度的话,可以定义成 BigInt 类型。

  • 示例

    let n1 = 100n;
    console.log(n1); // 100n
    console.log(typeof n1); // bigint
    
    // BigInt 类型数据只能与 BigInt 类型数据进行数学计算
    console.log(n1 + 40n); // 140n
    // console.log(n1 * 3); // 报错
    
    // BigInt 类型数据可以与 number 类型比较,自动类型转换
    console.log(n1 === 100); // false
    console.log(n1 == 100); // true
    console.log(n1 > 40); // true
    console.log(n1 > 400); // false
    
    // 也有二进制方式、八进制方式、十六进制方式
    let n2 = 0b101n;
    let n3 = 0o101n;
    let n4 = 0x101n;
    console.log(n2, n3, n4); // 5n, 65n, 257n

8. 函数新增特性

函数参数的默认值
  • 示例

    function fun(name, age = 100) {
        console.log(name, age);
    }
    fun('姬发'); // 姬发 100
    fun('姬发', 50); // 姬发 50
rest 参数
  • 示例

    let getSum = (...nums) => {
        let sum = 0;
        nums.forEach(item => {
            sum += item;
        });
        return sum;
    }
    console.log(getSum(4, 43, 5, 6, 7)); // 65
箭头函数
  • 语法

    let fn = (name, age) => {
        console.log(`我叫${name},我今年${age}岁`);
    };
    fn('gmy', '23');  //我叫gmy,我今年23岁
  • 简略写法

    • 省略 () 的条件:只有一个参数,多个参数或者没有参数都不能省略。

    • 省略 {} 的条件:函数体内只有一条返回值语句,省略 {}return

  • 示例

    let add = (a, b) => a + b;
    console.log(add(3, 4)); // 7
    
    let greet = name => `你好,${name}!`;
    console.log(greet('张三')); // 你好,张三!
箭头函数的特点
  • 箭头函数没有自己的 this,会取上层作用域的 this;因此箭头函数中的 this 与调用者无关,只与箭头函数声明的地方有关。

  • 箭头函数没有 arguments 但是可以有 rest 参数。

  • 箭头函数不可以作为构造函数,new 则报错。

  • 箭头函数不能使用 yield,无法创建生成器函数。

函数参数尾逗号(ES2017)
  • 示例

    function fn(name, age, ) {
        console.log(name, age);
    }
    fn('安妮', 109);  //安妮 109
    fn('安妮', 108, );  //安妮 108

9. 数组的新特性

扩展运算符
  • 示例

    function fun(a, b, c) {
        console.log(a, b, c, a + b + c);
    }
    var nums = [100, 200, 300, 250];
    
    fun(nums); // 输出 [100, 200, 300, 250], undefined, undefined, 100, 200, 300, 250undefinedundefined
    fun(...nums); // 输出 100, 200, 300, 600
扩展运算符的应用场景
  1. 用于函数传参

    let arr = [123, 54, 65, 324];
    console.log(Math.max(...arr)); // 324
  2. 复制数组

    let arr = [789, 534, 54, 234];
    var arr2 = [...arr];
    console.log(arr2); // [789, 534, 54, 234]
  3. 合并数组

    let arr1 = [43, 54, 56];
    let arr2 = [24, 6, 234];
    var arr3 = [...arr1, ...arr2];
    console.log(arr3); // [43, 54, 56, 24, 6, 234]
  4. 把类数组转换为纯数组

    var arr = [...document.all];
    var ary = [...'hello world'];
    console.log(ary); // ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
rest 元素
  • 示例

    let [first, ...seconds] = [10, 20, 30, 40, 50];
    console.log(first); // 10
    console.log(seconds); // [20, 30, 40, 50]
Array 构造函数本身新增的方法
  • ES6 新增方法

    • Array.from():把伪数组转换为纯数组。

    • Array.of():创建新数组,参数会作为数组中的元素,可以设置任意量的参数,基本可以用来代替 Array()new Array()

Array 实例新增方法
  • ES3

    • length

    • join()

    • slice()

    • push()

    • pop()

    • unshift()

    • shift()

    • concat()

    • splice()

    • reverse()

    • sort()

  • ES5

    • indexOf()

    • lastIndexOf()

    • forEach()

    • filter()

    • map()

    • some()

    • every()

    • reduce()

    • reduceRight()

  • ES6

    • find(callback):返回数组中第一个满足条件的元素,参数是回调函数,回调函数接受元素和索引,回调函数返回 true 表示条件满足。

    • findIndex(callback):返回数组中第一个满足条件的参数的索引,参数是回调函数,回调函数接受元素和索引,回调函数返回 true 表示条件满足。

    • fill(val [, start][, end]):用于填充数组,把数组中的指定元素替换为 val,后两个参数不填则替换全部。

    • entries():返回由数组的索引和值构成的遍历器对象。

    • keys():返回由数组的索引组成的遍历器对象。

    • values():返回由数组的值组成的遍历器对象。

    • includes(val):判断数组中是否包含指定值,返回布尔值(可以判断 NaN)。

    • flat(num):用于拉平数组(把多维数组转换为一维数组),参数可以指定拉多少层,默认是 1,可以设置参数为 Infinity(拉平任意维数组)。

    • flatMap():先对数组 map 处理再进行 flat 操作,只能拉平一层。

10. 对象新特性

对象声明时候的简写
  • 示例

    let [name, age, address, grade] = ['曹操', 32, '许昌', '魏国'];
    function getInfo() {
        console.log('getInfo');
    }
    
    let obj = {
        name,
        age,
        address,
        grade,
        getInfo
    };
声明对象时方法的简写
  • 示例

    let user = {
        name: '司马懿',
        age: 99,
        aoligei() {
            console.log('aoligei');
        }
    };
属性名表达式
  • 示例

    let prop = 'address';
    let obj = {
        [prop]: '上海',
        [1 + 7]: '丑',
        'user-name': '文丑',
        ['grade']: 66
    };
    console.log(obj); // { address: '上海', '8': '丑', 'user-name': '文丑', grade: 66 }
super 关键字
  • 示例

    class Parent {
        constructor() {
            this.name = 'Parent';
        }
        say() {
            console.log(`我是${this.name}`);
        }
    }
    
    class Child extends Parent {
        constructor() {
            super();
            this.name = 'Child';
        }
        say() {
            super.say();
            console.log(`我是${this.name}`);
        }
    }
    
    let child = new Child();
    child.say(); // 我是Parent 我是Child
对象的扩展运算符
  • 示例

    let obj1 = { a: 1, b: 2 };
    let obj2 = { b: 3, c: 4 };
    let obj3 = { ...obj1, ...obj2 };
    console.log(obj3); // { a: 1, b: 3, c: 4 }
对象的扩展运算符用于对象解构赋值
  • 示例

    let { gdx, ...df } = { name: 534, gdx: 'ok', ok: 54, fls: 'fsdj' };
    console.log(df); // { name: 534, ok: 54, fls: 'fsdj' }
Object 构造函数本身新增的方法
  • ES5 方法

    • Object.create():创建一个对象,指定对象的原型。

    • Object.defineProperty():添加属性,并指定属性的特性。

    • Object.defineProperties():添加多个属性,并指定属性的特性。

    • Object.getOwnPropertyDescriptor():获取对象中属性的特性。

  • ES6 方法

    • Object.is(arg1, arg2):用来判断参数是否相等,返回布尔值,与 === 的区别是,+0-0 不相等,NaNNaN 相等。

    • Object.assign(target, source1, source2...):合并对象,把第二个参数开始合并到第一个参数,并返回第一个参数(用于:对象合并,对象复制,对象默认值)。

    • Object.keys(obj):返回对象 obj 中所有属性名的数组集合。

    • Object.values(obj):返回 obj 中所有属性值的数组集合。

    • Object.entries(obj):返回对象中所有的属性名和属性值组成的二维数组。

    • Object.fromEntries()Object.entries 的逆运算。

    • Object.getOwnPropertyDescriptors():获取对象中所有的特性信息。

Object 实例新增的属性
  • __proto__ 属性(前后各两个下划线),用来读取或设置当前对象的原型对象。

11. Class 语法

使用 Class 定义类
  • 示例

    class User {
        name = '安妮';
        sex = '女';
    
        say() {
            console.log(`我叫${this.name},我的性别是${this.sex}`);
        }
    }
    
    let u1 = new User();
    u1.say(); // 我叫安妮,我的性别是女
类的语法特性
  • 类的本质还是构造函数,typeof 返回 function

  • 类只能用来实例化不能调用。

  • 类中只能定义属性和方法,不能直接使用 this(方法中才能写 this),不能写其他语句。

  • 类中定义的属性会添加到实例的本身,类中定义的方法会添加到实例的原型上面。

类中定义构造器方法
  • 示例

    class User {
        name = 'null';
        age = 'null';
        address = 'null';
    
        constructor(name, age, address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        say() {
            console.log(`我叫${this.name},今年${this.age}岁,住在${this.address}`);
        }
    }
    
    let u1 = new User('曹操', 99, '许昌');
    u1.say(); // 我叫曹操,今年99岁,住在许昌
静态方法
  • 示例

    class Foo {
        static classMethod() {
            return 'hello';
        }
    }
    
    console.log(Foo.classMethod()); // hello
访问器属性
  • 示例

    class Person {
        firstName = null;
        lastName = null;
    
        constructor(firstName, lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    
        get fullName() {
            return `${this.firstName}·${this.lastName}`;
        }
    
        set fullName(val) {
            if (val.includes('·')) {
                [this.firstName, this.lastName] = val.split('·');
            }
        }
    }
    
    let p1 = new Person('张', '三');
    console.log(p1.fullName); // 张·三
    p1.fullName = '李·四';
    console.log(p1.firstName); // 李
    console.log(p1.lastName); // 四
实现继承
  • 示例

    class Animal {
        color = null;
        weight = null;
    
        eat() {
            console.log('我是动物我会吃');
        }
    }
    
    class Person extends Animal {
        name = null;
    
        say() {
            console.log(`我叫${this.name}, 我的肤色是${this.color}, 我的重量是${this.weight}`);
        }
    }
    
    let p1 = new Person();
    p1.name = '刘备';
    p1.color = '白';
    p1.weight = 70;
    p1.say(); // 我叫刘备, 我的肤色是白, 我的重量是70
    p1.eat(); // 我是动物我会吃
方法和属性的重写
  • 示例

    class Animal {
        eat() {
            console.log('我是动物我会吃');
        }
    }
    
    class Person extends Animal {
        eat() {
            console.log('我是人类我会吃');
        }
    }
    
    let p1 = new Person();
    p1.eat(); // 我是人类我会吃
super 关键字
  • 示例

    class Person extends Animal {
        constructor(name, color, weight) {
            super(color, weight);
            this.name = name;
        }
    }
继承系统类(内置的构造函数)
  • 示例

    class MyArray extends Array {
        constructor(...args) {
            super(...args);
        }
    }
    
    let arr = new MyArray(1, 2, 3);
    console.log(arr); // [1, 2, 3]

12. 新增元素数据类型 Symbol

  • 定义Symbol 是 JavaScript 新增的一种原始类型数据,typeof 会返回 symbol

  • 创建:通过调用 Symbol() 可以创建 Symbol 类型的数据,注意,Symbol 只能调用不能实例化。

  • 特点

    • 每创建一个 Symbol 类型的数据,都是唯一的。

    • Symbol 类型的数据可以作为对象的属性名。

  • 示例

    let s1 = Symbol('s1');
    let s2 = Symbol('s2');
    
    console.log(s1 === s2); // false
    
    let obj = {
        [s1]: 'value1',
        [s2]: 'value2'
    };
    
    console.log(obj[s1]); // value1
    console.log(obj[s2]); // value2

13. 新增数据类型 Set 和 Map

Set 数据类型
  • 定义Set 是 ES6 新增的数据类型,跟数组类型相似,是值的集合,但是不能重复。

  • 构造函数Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

  • 实例方法

    • add():添加一个值。

    • delete():删除一个值。

    • has():判断是否包含某个值,返回布尔值。

    • clear():清空 Set 所有值。

    • forEach():遍历。

    • keys():返回遍历器对象。

    • values():返回遍历器对象。

    • entries():返回遍历器对象。

  • 属性

    • size:得到长度(类似于数组的 length)。

  • 示例

    const s = new Set([1, 3, 4, 5]);
    console.log(s.size); // 4
    
    s.add(6);
    console.log(s); // Set(5) {1, 3, 4, 5, 6}
    
    s.delete(3);
    console.log(s); // Set(4) {1, 4, 5, 6}
    
    console.log(s.has(4)); // true
    
    s.clear();
    console.log(s); // Set(0) {}
WeakSet 数据类型
  • 定义WeakSet 结构与 Set 类似,也是不重复的值的集合,但是它与 Set 有两个区别:

    • WeakSet 成员只能是对象。

    • WeakSet 不可遍历。

  • 构造函数:作为构造函数,WeakSet 可以接受一个数组(或者其他可遍历对象)作为参数。该数组的所有成员,都会自动成为 WeakSet 的实例对象的成员。

  • 实例方法

    • add(val)

    • delete(val)

    • has(val)

  • 示例

    const ws = new WeakSet();
    const obj1 = {};
    const obj2 = {};
    
    ws.add(obj1);
    ws.add(obj2);
    
    console.log(ws.has(obj1)); // true
    console.log(ws.has(obj2)); // true
    
    ws.delete(obj1);
    console.log(ws.has(obj1)); // false
Map 数据类型
  • 定义Map 类型数据类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。

  • 构造函数:任何具有 iterator 接口、且每个成员都是一个双元素的数据结构(数组和可遍历对象)都可以作为 Map 构造函数的参数。

  • 实例方法

    • get(key):根据 key 获取值。

    • set(key, val):根据 key 设置值。

    • has(key):判断是否存在指定的 key

    • delete(key):删除对应的 keyvalue

    • clear():清除所有的键值对。

    • keys():获取所有的 key 组成的遍历器对象。

    • values():获取所有的 value 组成的遍历器对象。

    • entries():获取所有的键值对组成的遍历器对象。

    • forEach(callback):用于遍历。

  • 属性

    • size:获取键值对的数量。

  • 示例

    let map = new Map([
        [1, 2],
        ['ok', 'fine'],
        [{ name: 'anni' }, 1]
    ]);
    
    console.log(map.get(1)); // 2
    console.log(map.get('ok')); // fine
    console.log(map.get({ name: 'anni' })); // 1
    
    map.set('newKey', 'newValue');
    console.log(map.has('newKey')); // true
    
    map.delete('newKey');
    console.log(map.has('newKey')); // false
    
    map.clear();
    console.log(map.size); // 0
WeakMap 数据类型
  • 定义WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合,WeakMapMap 的区别有两点:

    • WeakMap 只接受对象(所有的对象类型,除了原始类型)作为键名,不接受其他类型的值作为键名。

    • WeakMap 不可遍历。

  • 构造函数WeakMap 可以使用 set 方法添加成员,也可以接受一个数组作为构造函数的参数。

  • 实例方法

    • set(key, value)

    • get(key)

    • has(key)

    • delete(key)

  • 示例

    const wm1 = new WeakMap();
    const key = { foo: 1 };
    wm1.set(key, 2);
    console.log(wm1.get(key)); // 2
    
    const k1 = [1, 2, 3];
    const k2 = [4, 5, 6];
    const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
    console.log(wm2.get(k2)); // "bar"

14. Iterator 遍历器对象和可遍历对象

Iterator 遍历器对象
  • 定义Iterator(遍历器)是一种接口,为各种不同数据结构提供统一访问机制,任何数据只要部署 Iterator 接口,就可以完成遍历操作。

  • 特点

    • 每个 Iterator(遍历器)都有一个 next() 方法。

    • Iterator 遍历器内部存在一个指针,指针指向遍历器的第一个数据,调用 next(),会取出指针指向的数据,并且指针下移。

    • 每一次调用 next() 方法,都会返回数据结构的当前成员的信息,具体来说,就是返回包含 valuedone 两个属性的对象。其中 value 属性是当前成员的值,done 属性是一个布尔值表示遍历是否结束。

  • 示例

    var set = new Set([100, 200, 300, 400]);
    var setIterator = set.keys();
    let res = null;
    do {
        res = setIterator.next();
        if (res.value !== undefined) {
            console.log(res.value);
        }
    } while (!res.done);
Iterable 可遍历对象
  • 定义:把部署了 Iterator(遍历器对象)接口的数据结构称之为 iterable(可遍历对象)。

  • 特点

    • Iterator 接口部署在了数据结构的 Symbol.iterator 属性上,换句话说,一个对象,只有具有 Symbol.iterator 属性,且该属性指向一个返回 Iterator(遍历器对象)的函数,该对象就是 iterable(可遍历对象)。

  • 原生实现了 Iterator 接口的类型(可遍历对象)

    • Array

    • Set

    • Map

    • String

    • Arguments

    • NodeList

    • HTMLCollection

  • 可遍历对象和类数组(伪数组)

    • 类数组(伪数组):对象中有索引结构,有 length 属性,就是伪数组。

    • 可遍历对象:部署了 Iterator 接口的对象,才是可遍历对象。

  • 调用可遍历对象 Iterator 接口的场合

    • 数组解构赋值

    • 使用数组扩展运算符

    • Array.from()

    • for...of 遍历

    • Set 构造函数的参数

    • WeakSet 构造函数的参数

    • Map 构造函数的参数

    • WeakMap 构造函数的参数

    • Promise.all

    • Promise.race

  • 示例

    var arr = ['red', 'green', 'blue'];
    for (let k of arr) {
        console.log(k); // red, green, blue
    }

15. 生成器 Generator

定义
  • 生成器就是能创建遍历器的函数。

如何定义
  • 示例

    function* gen() {
        yield 1;
        yield 2;
        yield 3;
    }
    
    let iter = gen();
    console.log(iter.next().value); // 1
    console.log(iter.next().value); // 2
    console.log(iter.next().value); // 3
    console.log(iter.next().value); // undefined
yield 关键字
  • 特点

    • yield 关键字返回一个值,遍历的时候每次得到的就是 yield 的值。

    • 调用 next(),执行到 yield 就会停止,下次调用 next(),执行到下一个 yield 停止。

    • 调用生成器函数无论里面有没有 return,都会返回一个遍历器对象。

  • 示例

    function* gener() {
        yield '值1';
        yield '值2';
        yield '值3';
        yield '值4';
    }
    
    let gen = gener();
    console.log(gen.next().value); // 值1
    console.log(gen.next().value); // 值2
    console.log(gen.next().value); // 值3
    console.log(gen.next().value); // 值4
    console.log(gen.next().value); // undefined
return 可以终止生成器遍历
  • 示例

    function* gen() {
        yield 1;
        yield 2;
        return 3;
        yield 4; // 这行代码不会执行
    }
    
    let iter = gen();
    console.log(iter.next().value); // 1
    console.log(iter.next().value); // 2
    console.log(iter.next().value); // 3
    console.log(iter.next().value); // undefined
利用生成器对象部署 Iterator 接口
  • 示例

    var obj = {
        name: '安妮',
        age: 89,
        address: '上海',
        [Symbol.iterator]: function* () {
            for (var k in obj) {
                yield [k, obj[k]];
            }
        }
    };
    
    for (let [key, value] of obj) {
        console.log(key, value); // name 安妮, age 89, address 上海
    }

16. 模块(Module)

定义模块
  • 示例

    • module1.js

      export var firstName = 'anni';
      export function say() {
          console.log('hello world');
      }
    • module2.js

      var user = '典韦';
      function skill() {
          console.log('奥利给');
      }
      export default {
          user,
          skill
      };
模块导入
  • 示例

    • 导入 module1.js

      import { firstName, say } from './module1.js';
      console.log(firstName); // anni
      say(); // hello world
    • 导入 module2.js

      import myMod from './module2.js';
      console.log(myMod.user); // 典韦
      myMod.skill(); // 奥利给

17. 新增的运算符(ES2020)

可选链运算符 ?.
  • 定义:可选链运算符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。

  • 特点

    • ?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(null 或者 undefined)的情况下不会引起错误,该表达式短路返回值是 undefined

    • 与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

  • 示例

    const obj = {
        user: {
            name: 'anni'
        }
    };
    
    console.log(obj.user?.name); // anni
    console.log(obj.user?.age); // undefined
    
    console.log(obj.getInfo?.()); // undefined
空值合并运算符 ??
  • 定义:空值合并运算符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

  • 特点

    • 与逻辑或运算符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,''0)时。

  • 示例

    console.log(null ?? 2000); // 2000
    console.log(undefined ?? 2000); // 2000
    console.log(false ?? 2000); // false
    console.log(0 ?? 2000); // 0
    console.log('' ?? 2000); // 空字符串
    console.log(NaN ?? 2000); // NaN

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值