ES6~ES11

124 阅读15分钟

ES6

1.Let重复申明会报错 
在申明let/const类型数据之前进行该数据操作会报错,而var类型的数据会存在变量提升,
所以只会只是undefined,在let/const数据声明使用前的这一段时间就是暂时性死区
2.const能push但是不能用等号赋值 
3.rest参数,获取函数实参 
4.symbol 不能进行运算,不能用for in 遍历,可以使用Eeflect.ownKeys来获取键值 symbol.for("q")===symbol.for("q")"
5.  lterator 迭代器 自定义数组 具有[symbol.iterator]属性,
都可以for of 
6.生成器 generator yield 通过next执行,next传参为上一个yield语句返回结果 
7.class或者function中的静态变量数组类,实例new出来是没法获取到的 
8.class extends继承使用super,类似于使用了继承对象的constructor方法
9. class get set 中set必须有一个形参 
10.number.EPSTION 表示最小精度 
11.二进制0b开头 八进制0o开头 
12.Math.trunc把小数点抹去 Math.sign检测正数负数0
13.let` 和 `const`
14.Async await 是generator语法糖
15.Generator是分段方法,遇到yield会暂停 

|         | var | let | const |
| ------- | --- | --- | ----- |
| 变量提升    | √   | ×   | ×     |
| 全局变量    | √   | ×   | ×     |
| 重复声明    | √   | ×   | ×     |
| 重新赋值    | √   | √   | ×     |
| 暂时性死区   | ×   | √   | √     |
| 块作用域    | ×   | √   | √     |
| 只声明不初始化 | √   | √   | ×     |

  1. 类(Class) 在 ES6 之前,如果我们要生成一个实例对象,传统的方法就是写一个构造函数,例子如下: class为构造函数语法糖

    function Person(name, age) {
        this.name = name
        this.age = age
    }
    Person.prototype.information = function () {
        return 'My name is ' + this.name + ', I am ' + this.age
    }
    

    但是在 ES6 之后,我们只需要写成以下形式:

    class Person {
        constructor(name, age) {
            this.name = name
            this.age = age
        }
        information() {
            return 'My name is ' + this.name + ', I am ' + this.age
        }
    }
    

0.for…of for ... in ; for ... of 区别

  • for ... in 获取的是对象的键名;for ... of 遍历获取的是对象的键值
  • for ... in 会遍历对象的整个原型链,性能非常差,不推荐使用;而 for ... of 只遍历当前对象,不会遍历原型链
  • 对于数组的遍历,for ... in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性);for ... of 只返回数组的下标对应的属性值
  • 对于普通对象,没有部署原生的 iterator 接口,直接使用 for...of 会报错,也可以使用 Object.keys(obj) 方法将对象的键名生成一个数组,然后遍历这个数组
  • forEach 循环无法中途跳出,break 命令或 return 命令都不能奏效;for...of 循环可以与 break、continue 和 return 配合使用,跳出循环
  • for...in 循环主要是为了遍历对象而生,不适用于遍历数组;for...of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象
  1. Symbol symbol 是一种基本数据类型,表示独一无二的值。Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。 每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的。

    const symbol1 = Symbol();
    const symbol2 = Symbol(42);
    const symbol3 = Symbol('foo');
    
    console.log(typeof symbol1);  // "symbol"
    console.log(symbol3.toString());  // "Symbol(foo)"
    console.log(Symbol('foo') === Symbol('foo'));  // false
    
  2. 迭代器(Iterator)/ 生成器(Generator) 迭代器(Iterator)是一种迭代的机制,为各种不同的数据结构提供统一的访问机制。任何数据结构只要内部有 Iterator接口,就可以完成依次迭代操作。 一旦创建,迭代器对象可以通过重复调用 next() 显式地迭代,从而获取该对象每一级的值,直到迭代完,返回 { value: undefined, done: true }

    function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
        for (let i = start; i < end; i += step) {
            yield i;
        }
    }
    var a = makeRangeIterator(1,10,2)
    a.next() // {value: 1, done: false}
    a.next() // {value: 3, done: false}
    a.next() // {value: 5, done: false}
    a.next() // {value: 7, done: false}
    a.next() // {value: 9, done: false}
    a.next() // {value: undefined, done: true}
    
  3. Set / WeakSet Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

    const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
    console.log([...new Set(numbers)])  // [2, 3, 4, 5, 6, 7, 32]
    

    WeakSet 结构与 Set 类似,但区别有以下两点:

    • WeakSet 对象中只能存放对象引用,不能存放值,而 Set 对象都可以。

    • WeakSet 对象中存储的对象值都是被弱引用的,如果没有其他的变量或属性引用这个对象值,则这个对象值会被当成垃圾回收掉。正因为这样,WeakSet 对象是无法被枚举的,没有办法拿到它包含的所有元素。

    const ws = new WeakSet()
    const obj = {}
    const foo = {}
    
    ws.add(window)
    ws.add(obj)
    
    ws.has(window)  // true
    ws.has(foo)  // false, 对象 foo 并没有被添加进 ws 中 
    
    ws.delete(window)  // 从集合中删除 window 对象
    ws.has(window)  // false, window 对象已经被删除了
    
    ws.clear()  // 清空整个 WeakSet 对象
    
  4. Map / WeakMap Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。甚至可以使用 NaN 来作为键值。

    const myMap = new Map();
    myMap.set(NaN, "not a number");
    myMap.get(NaN);  // "not a number"
    
    const otherNaN = Number("foo");
    myMap.get(otherNaN);  // "not a number"
    

    WeakMap 对象是一组键 / 值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。跟 Map 的区别与 SetWeakSet 的区别相似。

    const o1 = {};
    const o2 = function(){};
    const o3 = window;
    
    const wm1 = new WeakMap();
    wm1.set(o1, 37);
    wm1.has(o1);  // true
    wm1.delete(o1);
    wm1.has(o1);  // false
    
    wm1.set(o2, "azerty");
    wm1.get(o2);  // "azerty"
    wm1.has(o2);  // true
    
    const wm2 = new WeakMap();
    wm2.set(o1, o2);  // value可以是任意值,包括一个对象
    wm2.get(o2);  // undefined,wm2中没有o2这个键
    wm2.has(o2);  // false
    
    wm2.set(o3, undefined);
    wm2.get(o3);  // undefined,值就是undefined
    wm2.has(o3);  // true (即使值是undefined)
    
    wm2.set(wm1, wm2);  // 键和值可以是任意对象,甚至另外一个WeakMap对象
     
    const wm3 = new WeakMap();
    wm3.set(o1, 37);
    wm3.get(o1);  // 37
    wm3.clear();
    wm3.get(o1);  // undefined,wm3已被清空
    
  5. Proxy / Reflect Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。 Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 Proxy 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

    const observe = (data, callback) => {
      return new Proxy(data, {
            get(target, key) {
                return Reflect.get(target, key)
            },
            set(target, key, value, proxy) {
                  callback(key, value);
                  target[key] = value;
                    return Reflect.set(target, key, value, proxy)
            }
      })
    }
    
    const FooBar = { open: false };
    const FooBarObserver = observe(FooBar, (property, value) => {
      property === 'open' && value 
          ? console.log('FooBar is open!!!') 
          : console.log('keep waiting');
    });
    console.log(FooBarObserver.open)  // false
    FooBarObserver.open = true  // FooBar is open!!!
    FooBarObserver.open = false // keep waiting
    
  6. Regex对象的扩展

    • u 修饰符: 为了处理码点大于 \uFFFFUnicode 字符(也就是说,会正确处理四个字节的 UTF-16 编码);\uD83D\uDC2A 是一个字符,但是 es5 不支持四个字节的 UTF-16,会将其识别成两个字符;加了 u 修饰符之后,es6 会将其识别成一个字符。

      // i 修饰符:不区分大小写
      /[a-z]/i.test('\u212A')  // false
      /[a-z]/iu.test('\u212A')  // true
      
    • y 修饰符:“粘连”(sticky)修饰符 y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

      var s = 'aaa_aa_a';
      var r1 = /a+/g;
      var r2 = /a+/y;
      
      r1.exec(s) // ["aaa"]
      r2.exec(s) // ["aaa"]
      
      r1.exec(s) // ["aa"]
      r2.exec(s) // null
      
    • 查看RegExp构造函数的修饰符

      new RegExp(/abc/ig, 'i').flags  //  "i"
      
  7. Array 对象的扩展

    • Array.from() 用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 SetMap)。

      Array.from('foo')  //  ["f", "o", "o"]
      // 扩展运算符(...)也可以将某些数据结构转为数组
      [ ...document.querySelectorAll('div') ]  //  NodeList对象
      Array.from({ length: 3 })  //  [ undefined, undefined, undefined ]
      Array.from([1, 2, 3], x => x + x)  //  [2, 4, 6]
      
    • Array.of():用于将一组值,转换为数组

      Array.of()  //  []
      Array.of(3, 11, 8)  //  [3,11,8]
      Array.of(3)  //  [3]
      Array.of(3).length  //  1
      
      // 这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
      Array()  //  []
      Array(7)  //  [empty, empty, empty, empty, empty, empty]
      Array(3, 11, 8)  //  [3, 11, 8]
      
    • 数组实例的 copyWithin() 在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组,会修改当前数组。 Array.prototype.copyWithin(target, start = 0, end = this.length) 它接受三个参数。这三个参数都应该是数值,如果不是,会自动转为数值。

      1. target(必需):从该位置开始替换数据。

      2. start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。

      3. end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

      ['a', 'b', 'c', 'd', 'e'].copyWithin(0, 3, 4)  //  ["d", "b", "c", "d", "e"]
      [1, 2, 3, 4, 5].copyWithin(0, 3)  //  [4, 5, 3, 4, 5]
      [1, 2, 3, 4, 5].copyWithin(0, -2, -1)  //  [4, 2, 3, 4, 5]
      
    • 数组实例的 find() 和 findIndex()

    • 数组实例的 fill()fill 方法使用给定值,填充一个数组

      ['a', 'b', 'c'].fill(7)  //  [7, 7, 7]
      new Array(3).fill(7)  //  [7, 7, 7]
      // 可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置
      ['a', 'b', 'c'].fill(7, 1, 2)  //  ['a', 7, 'c']
      [1, 2, 3, 4].fill(5, 1)  //  [1, 5, 5, 5]
      
    • 数组实例的 entries(),keys() 和 values()

      /*
      * 用于遍历数组,都返回一个遍历器对象,可以用 for...of 循环进行遍历
      * 唯一的区别是 keys() 是对键名的遍历、values() 是对键值的遍历、entries() 是对键值对的遍历
      */
      for (let index of ['a', 'b'].keys()) {
        console.log(index);
      }
      // 0
      // 1
      
      for (let elem of ['a', 'b'].values()) {
        console.log(elem);
      }
      // 'a'
      // 'b'
      
      for (let [index, elem] of ['a', 'b'].entries()) {
        console.log(index, elem);
      }
      // 0 "a"
      // 1 "b"
      
    • 数组的空位:明确将空位转为 undefined

ES7

数组实例的 `includes()` 返回一个布尔值,表示某个数组是否包含给定的值,与字符串的 `includes` 方法类似

    ```
    [1, 2, 3].includes(2);  //  true
    [1, 2, 3].includes(4);  //  false
    [1, 2, NaN].includes(NaN);  //  true
    ```

    该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,
    如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

    ```
    [1, 2, 3].includes(3, 3);  // false
    [1, 2, 3].includes(3, -1); // true
    ```

    > 另外,`Map``Set` 数据结构有一个 `has` 方法,需要注意与 `includes` 区分。
    1. `Map` 结构的has方法,
    是用来查找键名的,比如 `Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)`2. `Set` 结构的 `has` 方法,是用来查找值的,比如 `Set.prototype.has(value)、WeakSet.prototype.has(value)`。

幂运算符 `**`

    ```
    console.log(2**10) // 1024 类似于Math.pow(2, 10) 
    console.log(Math.pow(2, 10)) // 1024
    ```

模板字符串(Template string) 自 `ES7` 起,带标签的模版字面量遵守以下转义序列的规则:

    -   `Unicode` 字符以 `"\u"` 开头,例如 `\u00A9`
    -   `Unicode` 码位用"\u{}"表示,例如 `\u{2F804}`
    -   十六进制以 `"\x"` 开头,例如 `\xA9`
    -   八进制以 `""` 和数字开头,例如 `\251`

ES8

Object.entries () 将对象转换为二维数组
Object.values():返回一个给定对象自身的所有可枚举属性值的数组

    ```
    const object1 = {
      a: 'somestring',
      b: 42,
      c: false
    }
    console.log(Object.values(object1)) // ["somestring", 42, false]
    ```

 Object.entries():返回一个给定对象自身可枚举属性的键值对数组

    ```
    const object1 = {
        a: 'somestring',
        b: 42
    }
    console.log(Object.entries(object1)) // [["a","somestring"],["b",42]]
    for (let [key, value] of Object.entries(object1)) {
          console.log(`${key}: ${value}`)
    }
    // "a: somestring"
    // "b: 42"
    ```

 padStart():用另一个字符串填充当前字符串(重复,如果需要的话),以便产生的字符串达到给定的长度。填充从当前字符串的开始(左侧)应用的。

    ```
    const str1 = '5'
    console.log(str1.padStart(4, '0'))  //  "0005"
    // 若无第二个参数,用空格填充
    console.log(str1.padStart(4))  //  "   5"
    ```
 padEnd():用一个字符串填充当前字符串(如果需要的话则重复填充),返回填充后达到指定长度的字符串。从当前字符串的末尾(右侧)开始填充。

    ```
    const str1 = 'Breaded Mushrooms'
    console.log(str1.padEnd(25, '.'))  //  "Breaded Mushrooms........"
    const str2 = '200'
    console.log(str2.padEnd(5))  //  "200  "
    ```

 函数参数结尾逗号
 SharedArrayBuffer对象 `SharedArrayBuffer` 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 `ArrayBuffer` 对象,它们都可以用来在共享内存(`shared memory`)上创建视图。与 `ArrayBuffer` 不同的是,`SharedArrayBuffer` 不能被分离。

    ```
    // 参数length指所创建的数组缓冲区的大小,以字节(byte)为单位
    let sab = new SharedArrayBuffer(1024)  // 创建一个1024字节的缓冲
    ```

Atomics对象 `Atomics对象` 提供了一组静态方法用来对 `SharedArrayBuffer` 对象进行原子操作。

    -   `Atomics.add()`:将指定位置上的数组元素与给定的值相加,并返回相加前该元素的值。
    -   `Atomics.and()`:将指定位置上的数组元素与给定的值相与,并返回与操作前该元素的值。
    -   `Atomics.compareExchange()`:如果数组中指定的元素与给定的值相等,则将其更新为新的值,并返回该元素原先的值。
    -   `Atomics.exchange()`:将数组中指定的元素更新为给定的值,并返回该元素更新前的值。
    -   `Atomics.load()`:返回数组中指定元素的值。
    -   `Atomics.or()`:将指定位置上的数组元素与给定的值相或,并返回或操作前该元素的值。
    -   `Atomics.store()`:将数组中指定的元素设置为给定的值,并返回该值。
    -   `Atomics.sub()`:将指定位置上的数组元素与给定的值相减,并返回相减前该元素的值。
    -   `Atomics.xor()`:将指定位置上的数组元素与给定的值相异或,并返回异或操作前该元素的值。
    -   `Atomics.wait()`:检测数组中某个指定位置上的值是否仍然是给定值,是则保持挂起直到被唤醒或超时。返回值为 “ok”、“not-equal” 或 “time-out”。调用时,如果当前线程不允许阻塞,则会抛出异常(大多数浏览器都不允许在主线程中调用 wait())。
    -   `Atomics.wake()`:唤醒等待队列中正在数组指定位置的元素上等待的线程。返回值为成功唤醒的线程数量。
    -   `Atomics.isLockFree(size)`:可以用来检测当前系统是否支持硬件级的原子操作。对于指定大小的数组,如果当前系统支持硬件级的原子操作,则返回 true;否则就意味着对于该数组,Atomics 对象中的各原子操作都只能用锁来实现。此函数面向的是技术专家。

Object.getOwnPropertyDescriptors():用来获取一个对象的所有自身属性的描述符

    ```
    const obj = {
      foo: 123,
      get bar() { return 'abc' }
    };
    ​
    Object.getOwnPropertyDescriptors(obj)
    // { foo:
    //    { value: 123,
    //      writable: true,
    //      enumerable: true,
    //      configurable: true },
    //   bar:
    //    { get: [Function: bar],
    //      set: undefined,
    //      enumerable: true,
    //      configurable: true } }
    ```

    -   浅拷贝一个对象 [`Object.assign()`](https://links.jianshu.com/go?to=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FJavaScript%2FReference%2FGlobal_Objects%2FObject%2Fassign) 方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性们,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型,该方法配合 [`Object.create()`](https://links.jianshu.com/go?to=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FJavaScript%2FReference%2FGlobal_Objects%2FObject%2Fcreate) 方法可以实现上面说的这些。

        ```
        Object.create(
          Object.getPrototypeOf(obj),
          Object.getOwnPropertyDescriptors(obj)
         );
        ```

    -   创建子类 创建子类的典型方法是定义子类,将其原型设置为超类的实例,然后在该实例上定义属性。这么写很不优雅,特别是对于 getters 和 setter 而言。 相反,您可以使用此代码设置原型:

        ```
        function superclass() {}
        superclass.prototype = {
          // 在这里定义方法和属性
        };
        function subclass() {}
        subclass.prototype = Object.create(superclass.prototype, Object.getOwnPropertyDescriptors({
          // 在这里定义方法和属性
        }));
        ```

\

ES9

1.对正则捕获到的数据进行分组
2.正则 正向断言?=
let str='JS5211314你知道么555啦啦啦'
const reg=/\d+(?=啦)/
const result=reg.exec(str)
反向断言
const reg=/(?<=么)\d+/
const result=reg.exec(str)
3.正则//s 结尾添加s 则点号可以匹配任意字符
  1. for await…of for await...of 语句创建一个循环,该循环遍历异步可迭代对象以及同步可迭代对象,包括: 内置的 String, Array,类似数组对象 (例如 argumentsNodeList),TypedArray, Map, Set 和用户定义的异步/同步迭代器。其会调用自定义迭代钩子,并为每个不同属性的值执行语句。

    async function* asyncGenerator() {
      var i = 0
      while (i < 3) {
            yield i++
      }
    }
    ​
    (async function() {
      for await (num of asyncGenerator()) {
            console.log(num)
      }
    })()
    // 0
    // 1
    // 2
    
  2. 模板字符串(Template string) ES9 开始,模板字符串允许嵌套支持常见转义序列,移除对 ECMAScript 在带标签的模版字符串中转义序列的语法限制。

  3. 正则表达式 Unicode 转义 正则表达式中的 Unicode 转义符允许根据 Unicode 字符属性匹配 Unicode 字符。 它允许区分字符类型,例如大写和小写字母,数学符号和标点符号。

    // 匹配所有数字
    const regex = /^\p{Number}+$/u;
    regex.test('²³¹¼½¾') // true
    regex.test('㉛㉜㉝') // true
    regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true// 匹配所有空格
    \p{White_Space}
    ​
    // 匹配各种文字的所有字母,等同于 Unicode 版的 \w
    [\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]// 匹配各种文字的所有非字母的字符,等同于 Unicode 版的 \W
    [^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]// 匹配 Emoji
    /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu// 匹配所有的箭头字符
    const regexArrows = /^\p{Block=Arrows}+$/u;
    regexArrows.test('←↑→↓⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩') // true
    
  4. 正则表达式 s/dotAll 模式 JS 正则增加了一个新的标志 s 用来表示 dotAll,这可以匹配任意字符。

    const re = /foo.bar/s;  //  等价于 const re = new RegExp('foo.bar', 's');
    re.test('foo\nbar');    // true
    re.dotAll;      // true
    re.flags;       // "s"
    

具名组匹配

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
​
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31

对象扩展操作符

fetch(url)
    .then((res) => {
      console.log(res)
    })
    .catch((error) => { 
      console.log(error)
    })
    .finally(() => { 
      console.log('结束')
  })

ES10

1.Object.fromEntries() 获取key和value 将数组转换为对象
2.flatMap 两个操作的结合 flat Map
3.Symbol.prototype.description 获取symbol的描述 s.description

数组实例的 flat() 用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。参数 depth 表示要提取嵌套数组的结构深度,默认值为 1。

console.log([1 ,[2, 3]].flat());  //  [1, 2, 3]// 指定转换的嵌套层数
console.log([1, [2, [3, [4, 5]]]].flat(2));  //  [1, 2, 3, [4, 5]]// 不管嵌套多少层【使用 Infinity 作为深度,展开任意深度的嵌套数组】
console.log([1, [2, [3, [4, 5]]]].flat(Infinity));  //  [1, 2, 3, 4, 5]// 自动跳过空位【会移除数组中的空项】
console.log([1, [2, , 3]].flat());  //  [1, 2, 3]// 传入 <=0 的整数将返回原数组,不“拉平”
console.log([1, [2, [3, [4, 5]]]].flat(0));  //  [1, [2, [3, [4, 5]]]]
console.log([1, [2, [3, [4, 5]]]].flat(-10));  //  [1, [2, [3, [4, 5]]]]

数组实例的 flatMap() 首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。

[1, 2, 3, 4].flatMap(x => x * 2);  //  [2, 4, 6, 8]
[1, 2, 3, 4].flatMap(x => [x * 2]);  //  [2, 4, 6, 8][1, 2, 3, 4].flatMap(x => [[x * 2]]);  //  [[2], [4], [6], [8]]
[1, 2, 3, 4].map(x => [x * 2]);  //  [[2], [4], [6], [8]]

字符串实例的 trimStart() / trimLeft() / trimEnd() / trimRight() 去除字符首或尾的空格,trimStart()trimEnd() 才是标准方法,trimLeft()trimRight() 只是别名 Object.fromEntries() 把键值对列表转换为一个对象,它是 Object.entries() 的反函数。

const entries = new Map([  ['foo', 'bar'],
  ['baz', 42]
])
console.log(Object.fromEntries(entries))  //  Object { foo: "bar", baz: 42 }

Symbol.prototype.description 通过工厂函数 Symbol() 创建符号时,您可以选择通过参数提供字符串作为描述:

Symbol('desc').toString();  //  "Symbol(desc)"
Symbol('desc').description;  //  "desc"
Symbol('').description;  //  ""
Symbol().description;  //  undefined//全局 symbols
Symbol.for('foo').toString();  //  "Symbol(foo)"
Symbol.for('foo').description;  //  "foo"

Function.prototype.toString() 现在返回精确字符,包括空格和注释 try-catch catch 的参数可省略

ES11

1.私有属性 #age #weight
2.promise.allSettled([]) 返回所有promise的状态和数组
3.matchAll 获取所有的匹配到的iteratoer数组,可以用扩展运算符或者for of
4.Bight 大整型 只对整型int有效 Bight只能和Bight进行运算
5.globalThis 全局对象

String.prototype.matchAll 返回一个包含所有匹配正则表达式及分组捕获结果的迭代器。

var regexp = /t(e)(st(\d?))/g
var str = 'test1test2'str.match(regexp)  //  ['test1', 'test2']
str.matchAll(regexp)  //  RegExpStringIterator {}
[...str.matchAll(regexp)]  //  [ ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4], ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4] ]

动态 import()

const modelpath = '/demo'
import(`@/pages${modelpath}`).then(module => {}).catch(err => {})
  1. import.meta import.meta 会返回一个对象,有一个 url 属性,返回当前模块的 url 路径,只能在模块内部使用。
  2. export * as XX from 'module'import * as XX from 'module'
  3. BigInt 现在的基本数据类型(值类型)不止5种(ES6之后是六种)了哦!加上 BigInt 一共有七种基本数据类型,分别是: String、Number、Boolean、Null、Undefined、Symbol、BigInt BigInt 可以表示任意大的整数。可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()
  4. globalThis 指向全局对象,浏览器下指向 window
  5. 可选链操作符(?.) info.animal?.reptile?.tortoise
  6. 空值合并操作符(??) 当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。 与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。
const foo = null ?? 'default string';
console.log(foo);  // "default string"
​
const baz = 0 ?? 42;
console.log(baz);  // 0

ES12

0.  `String.prototype.replaceAll` `replaceAll` 返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉,替换规则可以是字符串或者正则表达式。

let string = 'I like 前端,I like 前端公虾米' console.log(string.replace(/like/g,'love'))  // 'I love 前端,I love 前端公虾米' console.log(string.replaceAll('like','love'))  // 'I love 前端,I love 前端公虾米'


> 需要注意的是,`replaceAll` 在使用正则表达式的时候,如果非全局匹配(`/g`),则 `replaceAll()` 会抛出一个异常

console.log(string.replaceAll(/like/,'love'))  // TypeError


2.  `WeakRefs` 当我们通过(`const、let、var`)创建一个变量时,垃圾收集器 `GC` 将永远不会从内存中删除该变量,只要它的引用仍然存在可访问。`WeakRef` 对象包含对对象的弱引用。对对象的弱引用是不会阻止垃圾收集器 `GC` 恢复该对象的引用,则 `GC` 可以在任何时候删除它。 `WeakRefs` 在很多情况下都很有用,比如使用 `Map` 对象来实现具有很多需要大量内存的键值缓存,在这种情况下最方便的就是尽快释放键值对占用的内存。 目前,可以通过 `WeakMap()` 或者 `WeakSet()` 来使用 `WeakRefs`2.  逻辑运算符和赋值表达式 表达式 `a op= b` 等同于 `a = a op (a = b)`

a ||= b //等价于 a = a || (a = b)  // 当LHS值不存在时,将RHS变量赋值给LHS ​ a &&= b //等价于 a = a && (a = b)  // 当LHS值存在时,将RHS变量赋值给LHS ​ a ??= b //等价于 a = a ?? (a = b)  // 当LHS值为null或者undefined时,将RHS变量赋值给LHS


0.  数字分隔符号 数字分隔符,可以在数字之间创建可视化分隔符,通过 `_` 下划线来分割数字,使数字更具可读性

const money = 1_000_000_000 //等价于 const money = 1000000000 ​ const totalFee = 1000.12_34 //等价于 const totalFee = 1000.1234 ​ // 该新特性同样支持在八进制数中使用 const number = 0o123_456 //等价于 const number = 0o123456


\