• ES知识点全面整理


    ● 我们从很多年前就知道 ES6, 也就是官方发布的 ES2015

    ● 从 2015 年开始, 官方觉得大家命名太乱了, 所以决定以年份命名

    ● 但是大家还是习惯了叫做 ES6, 不过这不重要

    ● 重要的是, ES6 关注的人非常多, 大家也会主动去关注

    ● 但是从 2016 年以后, 每年官方都会出现新的语法, 那么大家又有多少关注呢

    ES2016 ( ES7 )

    ● 更新的内容并不多, 更像是在基于 ES2015( ES6 ) 的补充内容

    1.  数组方法扩展

    ● Array.prototype.includes()

    ● 语法 : Array.prototype.includes( search[, fromIndex] )

    ● 返回值 : 布尔值

    ● 基础应用 : 判断数组是否包含指定内容

    1. const arr = [ 'es6', 'es7', 'es8', 'es9' ]
    2. const r1 = arr.includes( 'es8' )
    3. console.log(r1) // => true
    4. const r2 = arr.includes( 'es5' )
    5. console.log(r2) // => false

    ● 通过第二个参数确定查询起始索引位置

    1. const arr = [ 'es6', 'es7', 'es8', 'es9' ]
    2. const r1 = arr.includes( 'es8', 1 )
    3. console.log(r1) // => 表示从索引 1 位置开始检索, 结果为 true
    4. const r2 = arr.includes( 'es8', 3 )
    5. console.log(r2) // => 表示从索引 3 位置开始检索, 结果为 false

    ● 第二个参数也可以填写负整数, 表示倒数第几个开始检索

    1. const arr = [ 'es6', 'es7', 'es8', 'es9' ]
    2. const r1 = arr.includes( 'es8', -1 )
    3. console.log(r1) // => 表示从索引 3 位置开始检索, 结果为 false
    4. const r2 = arr.includes( 'es8', -3 )
    5. console.log(r2) // => 表示从索引 1 位置开始检索, 结果为 true

    ● 冷知识 : includes 方法可以检测到 NaN 这玩意儿~~

    1. const arr = [ 'es6', 'es7', 'es8', NaN, 'es9' ]
    2. const r1 = arr.includes( NaN )
    3. console.log(r1) // => true

    2.  运算符扩展 : 幂运算符

    ● ** 符号

    ● 是一个取幂的符号, 等价于 Math.pow() 方法

    1. const r1 = 2 ** 10
    2. // 等价于 Math.pow(2, 10)
    3. console.log(r1) // => 1024

    ES2017 ( ES8 )

    ● 更新的内容也不是很多, 也是为了 ES2015( ES6 ) 做了一些补充扩展

    1.  异步解决方案的语法糖 async / await

    ● 两个关键字 async 和 await

    ● 用于对 Promise 的优化书写方案

    ● async

            ○ 书写在函数前面

            ○ 为了在该函数内可以使用 await 关键字

    ● await

            ○ 需要书写在一个有 async 关键字的函数内

            ○ 用于等待 Promise 的结果

            ○ 可以捕获到 Promise 成功的状态

    ● 例子 :

    1. function ajax() {
    2. return Promsie(() => { /* ... */ })
    3. }
    4. async function fn() {
    5. const res = await ajax()
    6. console.log(res)
    7. }
    8. fn()

            ○ 当 fn 调用的时候, 因为 ajax 方法内封装返回的是一个 Promise 对象

            ○ 因为使用了 async / await 关键字

            ○ 所以会在这一段异步代码结束后, 把 success 的结果给到 res 以后, 再继续向后执行代码

    2.  对象扩展 : Object.values()

    ● Object.values()

    ● 用于获取到对象内的每一个 值

    ● 返回值 : 是一个数组, 包含对象内每一个值

    1. const obj = {
    2. name: '码农键盘上的梦',
    3. age: 8,
    4. desc: '扛把子'
    5. }
    6. const res = Object.values(obj)
    7. console.log(res) // => [ '码农键盘上的梦', 8, '扛把子' ]

    3.  对象扩展 : Object.entries()

    ● Object.entries()

    ● 用于将给定对象的可枚举属性转化为一个包含键值对的数组

    ● 返回值 : 是一个二维数组, 和 for ... in 遍历出来的顺序是一样的

    1. const obj = {
    2. name: '码农键盘上的梦',
    3. age: 8,
    4. desc: '扛把子'
    5. }
    6. const res = Object.entries(obj)
    7. cosnole.log(res)
    8. /*
    9. [
    10. [ 'name', '码农键盘上的梦' ],
    11. [ 'age', 8 ],
    12. [ 'desc', '扛把子' ]
    13. ]
    14. */

    4.  对象扩展 : Object.getOwnPropertyDescriptors()

    ● Object.getOwnPropertyDescriptors( 对象 )

    ● 返回对象内每一个自身属性的描述详细信息

    ● 信息内可能包含的值为 configurable / enumerable / wrieable / value / get / set

    1. const obj = {
    2. name: '码农键盘上的梦',
    3. age: 8,
    4. desc: '扛把子'
    5. }
    6. const res = Object.getOwnPropertyDescriptors( obj )
    7. /*
    8. {
    9. age: {
    10. configurable: true,
    11. enumerable: true,
    12. value: 8,
    13. writable: true
    14. },
    15. desc: {
    16. configurable: true,
    17. enumerable: true,
    18. value: '扛把子',
    19. writable: true
    20. },
    21. name: {
    22. configurable: true,
    23. enumerable: true,
    24. value: '码农键盘上的梦',
    25. writable: true
    26. }
    27. }
    28. */

    5.  字符串方法扩展

    ● String.prototype.padStart() / String.prototype.padEnd()

    ● 用于填充字符串, 分别是在 开始位置填充 和 结束位置填充

    ● 语法 :

            ○ String.prototype.padStart( length, str )

            ○ String.prototype.padEnd( length, str )

    ● 注意 : 如果你的 length 小于字符串本身的 length, 那么不进行填充, 返回原始字符串

    ● 示例 :

    1. const str = '123456789'
    2. // 将 str 字符串填充至 length 为 15, 用 'abc' 进行填充
    3. const res = str.padStart( 15, 'abc' )
    4. console.log(res) // => 'abcabc123456789'
    1. const str = '123456789'
    2. // 将 str 字符串填充至 length 为 11, 用 'abc' 进行填充
    3. const res = str.padStart( 11, 'abc' )
    4. console.log(res) // => 'ab123456789'
    1. const str = '123456789'
    2. // 将 str 字符串填充至 length 为 8, 用 'abc' 进行填充
    3. const res = str.padStart( 8, 'abc' )
    4. console.log(res) // => '123456789'

    ● String.prototype.padEnd() 方法的语法和参数是一样的, 只不过是填充在结尾位置

    6.  尾逗号扩展

    ● 在函数定义和调用的时候, 可以在参数结尾位置添加一个逗号而不报错

    1. function fn(a, b, c,) {
    2. console.log(a, b, c)
    3. }
    4. fn(102030,)

    ES2018 ( ES9 )

    1.  异步扩展 : for await of

    ● 用于遍历异步的 Iterator 接口

    1. // 封装一个异步函数
    2. function ajax() { /* ... */ }
    3. async function fn() {
    4. const arr = [ ajax(), ajax(), ajax() ]
    5. for await ( let item of arr ) {
    6. console.log(Date.now(), item)
    7. }
    8. }
    9. fn()

    2.  Promise 方法扩展 : Promise.prototype.finally()

    ● 表示 Promise 完成

    ● 不管一个 Promise 最终是转换到 fulfilled 或者 rejected 状态, 在执行完 then 或者 catch 回调以后, 都会执行一下 finally 回调

    1. const p = new Promise((resolve, reject) => { /* ... */ })
    2. p.then(res => { /* ... */ })
    3. .catch(err => { /* ... */ })
    4.  .finally(() => { /* ... */ })

    3.  对象的扩展运算符 : ...

    ● 可以用于从一个对象内取值, 相当于将目标对象内的所有可遍历但是尚未被获取的属性, 分配到一个新的对象上, 一般用于解构赋值

    1. const obj = {
    2. name: '码农键盘上的梦',
    3. age: 8,
    4. desc: '扛把子',
    5. score: 100
    6. }
    7. const { name, age, ...info } = obj
    8. /*
    9. name '码农键盘上的梦'
    10. age 8
    11. info { desc: '扛把子', score: 100 }
    12. */
            ○ 注意 : ... 运算符一定要放在最后
    

    4.  正则扩展 : dotAll 模式

    ● 正则内的 点(.)

            我们都知道, 在正则表达式内 点(.) 是一个非常特殊的字符

            表示的是任意字符, 但是有两个例外

                1.  四个自己的 UTF-16 字符, 不过这个可以用 u 修饰符解决

                2.  终止符, 点( . ) 表示不了

                U+000A 换行符 ( \n )

                U+000D 回车符 ( \r )

                U+2028 行分隔符

                U+2029 段分隔符

    ● 现在扩展了一个 s 修饰符

        当你在书写正则表达式的时候, 如果用了 s 修饰符

        表示进入了 dotAll 模式, 既 点(.) 可以表示一切字符, 没有例外

    1. const r1 = /a.b/
    2. console.log(r1.test('a\nb')) // => false
    3. const r2 = /a.b/s
    4. console.log(r2.test('a\nb')) // => true

    ● 配合 s 修饰符, 正则还给出了一个 dotAll 属性, 用来指出当前正则是否处在 dotAll 模式

    1. const r1 = /a.b/
    2. const r2 = /a.b/s
    3. console.log(r1.dotAll) // => false
    4. console.log(r2.dotAll// => true

    5.  正则扩展 : 具名组匹配

    ● 在正则表达式内, 小括号 可以表示一个单独的小分组进行单独捕获

    ● 在使用 exec 方法的时候, 会把每一个 小括号 的内容单独捕获出来

    1. const str = '我学前端的时间 2015-05-18'
    2. const reg = /(\d{4})-(\d{2})-(\d{2})/
    3. const res = reg.exec(str)
    4. console.log( res )
    5. /*
    6. [
    7. 0: '2015-05-18',
    8. 1: '2015',
    9. 2: '05',
    10. 3: '18',
    11. index: 0,
    12. input: '我学前端的时间 2015-05-18'
    13. groups: undefined
    14. ]
    15. [0] 捕获出来的完整字符串片段
    16. [1] - [n] 分别表示每一个小括号单独捕获的内容
    17. index 匹配内容的开始索引位置
    18. input 原始字符串
    19. groups 一个捕获组, 在没有定义命名捕获组的时候是 undefined
    20. */

    ● 这就是以前正则捕获的结果

            会发现, 可以把每一个小分组内容捕获出来, 但是我们用起来的时候不是很方便

            如果我想单独使用小分组单独捕获出来的内容

            res[0]

            res[1]

            res[2]

    ● 现在, 添加了正则内小分组命名的能力, 我们可以给每一个小分组起名字

    ● 语法 : (?<名字>正则)

    1. const str = '我学前端的时间 2015-05-18'
    2. const reg = /(?\d{4})-(?\d{2})-(?\d{2})/
    3. const res = reg.exec(str)
    4. console.log( res )
    5. /*
    6. [
    7. 0: '2015-05-18',
    8. 1: '2015',
    9. 2: '05',
    10. 3: '18',
    11. index: 0,
    12. input: '我学前端的时间 2015-05-18'
    13. groups: {
    14. year: '2015',
    15. month: '05',
    16. date: '18'
    17. }
    18. ]
    19. */

    ES2019 ( ES10 )

    1.  数组扩展 : Array.prototype.flat() 和 Array.prototype.flatMap()

    ● Array.prototype.flat( 数字 ) 方法用于数组扁平化

    ● 参数表示扁平化时的递归深度, 默认是 1

    1. const arr1 = [ 1, 2, [ 3, 4 ] ]
    2. console.log(arr1.flat()) // => [ 1, 2, 3, 4 ]
    3. const arr2 = [ 1, 2, [ 3, 4, [ 5, 6, [ 7, 8 ] ] ] ]
    4. console.log(arr2.flat()) // => [ 1, 2, 3, 4, [ 5, 6, [ 7, 8 ] ] ]
    5. const arr3 = [ 1, 2, [ 3, 4, [ 5, 6, [ 7, 8 ] ] ] ]
    6. console.log(arr3.flat(2)) // => [ 1, 2, 3, 4, 5, 6, [ 7, 8 ] ]
    7. const arr4 = [ 1, 2, [ 3, 4, [ 5, 6, [ 7, 8 ] ] ] ]
    8. console.log(arr4.flat(Infinity)) // => [ 1, 2, 3, 4, 5, 6, 7, 8 ]

    ● Array.prototype.flatMap() 方法也是用于扁平化

            这个方就相当于是一个对组通过 map 映射, 然后通过 flat 扁平化

            但是他的扁平深度只能是 1

            arr.flatMap()

            等价于

            arr.map().flat(1)

    1. const arr = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]
    2. const res = arr.flatMap( x => x * 10 )
    3. console.log(res) // => [ 10, 20, NaN ]

    2.  对象扩展 : Object.fromEntries()

    ● 利用给定的键值对构建一个对象数据结构

    ● 它的功能刚好和 Object.entries() 是相反的

    1. const entries = new Map([
    2. [ 'name', '码农键盘上的梦' ],
    3. [ 'age', 8 ],
    4. [ 'desc', '扛把子' ]
    5. ])
    6. const res = Object.fromEntries(entries)
    7. console.log(res)
    8. /*
    9. {
    10. name: '码农键盘上的梦',
    11. age: 8,
    12. desc: '扛把子'
    13. }
    14. */

    3.  字符串扩展 : String.prototype.trimStart() 和 trimEnd()

    ● 这两个方法其实以前就有过, 叫做 trimLeft() 和 trimRight()

    ● 只不过在 ES2019 中, 名称被更改为 trimStart 和 trimEnd 只是为了看起来更直观

    ● trimStart() 修剪字符串的开头空白

    ● trimEnd() 修剪字符串的结尾空白

    1. const str = ' 码农键盘上的梦 '
    2. console.log(str.trimStart())
    3. // => '码农键盘上的梦 '
    4. console.log(str.trimEnd())
    5. // => ' 码农键盘上的梦'

    4.  Symbol 扩展 : Symbol.prototype.description

    ● 我们在创建 Symbol 的时候, 其实是可以添加一个描述的

    ● 但是将来你如果想要取会这个描述就比较麻烦了

            以前

            我们只能利用 toString 方法, 拿到 Symbol 的字符串

            然后自己从字符串中把我们定义 Symbol 的时候添加的描述拿回来

    1. const sy = Symbol( '码农键盘上的梦' )
    2. const origin = sy.toString()
    3. console.log(origin) // => 'Symbol(码农键盘上的梦)'

            ○ 我们自己从 origin 内把我们需要的描述信息截取出来

            ○ 比较麻烦

    ● 在 ES2019 内, 给 Symbol 添加了一个只读属性, 叫做 description

    ● 可以直接拿到每一个 Symbol 初始化的时候填写描述信息

    1. const sy = Symbol( '码农键盘上的梦' )
    2. console.log(sy.description// => '码农键盘上的梦'

    5.  可选 catch 绑定

    ● 先来看一下以前的 catch 语法

    1. try {
    2. const data = JSON.parse(response)
    3. } catch (err) {
    4. console.log('执行出错了, 错误信息是 : ', err)
    5. }

    ● 以前的语法迫使我们必须给 catch 绑定一个异常变量

    ● 但是其实大部分的时候, 我们是不需要用到这个变量的

    ● 但是在开发过程中, 不写又会报错, 这就使得我们每次都要写上

    ● 但是在 ES2019 的提案中, 让我们可以忽略掉这个变量

    1. try {
    2. const data = JSON.parse(response)
    3. } catch {
    4. console.log('执行出错了')
    5. }

    6.  JSON 扩展 : Superset 超集

    ● 并不是一个什么新的东西, 只是对 JSON 解析的能力进行了扩展

    ● 以前, JSON 在解析的时候, 如果字符串中包含有 分隔符(\u2028) 或者 段落分隔符(\u2029) 是不能被解析的, 会在解析过程中报错

    JSON.parse('"\u2028"'// => SyntabError

    ● 从 ES2019 以后, 可以解析这些内容了

    JSON.parse('"\u2028"'// => ''

    7.  JSON 扩展 : stringify 加强格式转化

    ● 也是增强了 JSON 在格式转换的时候的能力

    ● 主要是针对于 emoji 的表现

    ● 以前, emoji 和一些其他特殊字符被表示为两个代理项的组合, 如果我们用 JSON 进行格式转换的时候, 会被转换为无效字符

    JSON.stringify('😎'// => '"�"'

    ● ES2019 加强以后, 会在特有代码之前插入转义符, 结果依旧是一个可读且有效的 UTF-8 / UTF-16 的编码

    JSON.stringify('😎'// => '"\\ud83d"'

    ES2020 ( ES11 )

    1.  可选链操作符

    ● 在 JavaScript 的操作中, 我们经常会访问一些属性, 但是如果他的前置是未定义的呢 ? 是不是就会报错了呢

    ● 这个时候我们不确定他的前置是不是确实存在, 那么我们怎么办呢 ?

    ● 只能是任由他报错, 如果要做一些容错处理, 那么只能是 try catch 了, 但是这样的代码太难受了看起来

    ● 在 ES2020 中出现了一个新的运算符, 可选链运算符 ( ?. ), 帮我们解决了这个问题

    ● 意义 : 当前置是 undefined 的时候, 不在继续向后访问属性, 直接返回 undefined

    1. const obj = {
    2. info: { a: 100, b: 200 }
    3. }
    4. // 正常访问没有问题
    5. console.log(obj.info.a) // => 100
    6. // 当我们访问一个没有的前置的时候
    7. console.log(obj.desc.a) // => 报错
    8. // 这个时候就可以使用可选链运算符来代替
    9. // 如果 obj.desc 存在, 那么继续向后访问
    10. // 如果 obj.desc 不存在, 那么不继续向后访问
    11. console.log(obj.desc?.a) // => undefined

    2.  空值运算符 ( ?? )

    ● 这是一个非常简单的操作符, 和 || 操作符差不多, 但是又不太一样

    ● 只有当运算符左侧是 null 或者 undefined 的时候, 才会返回右侧的操作数据, 否则就返回左侧的操作数据

            || 运算符

            如果左侧为 假值 的时候, 就会返回右侧的数据

            ? 运算符

            只有左侧为 null 或 undefined 的时候, 才会返回右侧的数据

    1. const r1 = false || '码农键盘上的梦'
    2. console.log(r1) // => 码农键盘上的梦
    3. const r2 = false ?? '码农键盘上的梦'
    4. console.log(r2) // => false

    3.  类的私有变量

    ● 在 ES2020 中, 扩展了类的私有变量

    ● 当你创建一个类以后, 你可能希望这个类在不同位置使用, 但是你又不希望类里面的某个或者某些属性可以全局使用, 而只是在类内部使用

    ● 此时, 你可以在类里面定义该属性的时候使用一个 哈希符号

    1. class Person {
    2. // 定义了一个私有变量, 这个数据只能在类内部使用
    3. #age = 18
    4. getAge () { console.log(this.#age) }
    5. }
    6. const p = new Person()
    7. p.getAge()
    8. console.log(p.#age) // => 18

    4.  Promise 方法扩展 : Promise.allSettled()

    ● 当我们在使用多实例 promise 的时候, 特别是当这些 promise 实例之间还有互相依赖的关系的时候, 我们需要拿到每一个 promise 的结果

    ● 现在, ES2020 为我们提供可一个 allSettled 方法, 可以实现这个功能

    1. const p1 = new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. resolve('成功')
    4. }, 1000)
    5. })
    6. const p2 = new Promise((resolve, reject) => {
    7. setTimeout(() => {
    8. reject('失败')
    9. }, 1000)
    10. })
    11. Promise.allSettled([ p1, p2 ]).then(res => {
    12. console.log(res)
    13. })
    14. /*
    15. [
    16. { status: 'fulfilled', value: '成功' },
    17. { status: 'rejected', reason: '失败' }
    18. ]
    19. */

    5.  数据类型扩展 : bigInt

    ● 我们在 JS 的开发中, 一般不会涉及到非常大的数字, 以前我们也没有想过有一天我们也要涉及一些及其大的数字

    ● 但是当有一天我们真的遇到了, 发现我们没办法准确的把握这些数字了

    ● 因为 js 能处理的最大的数字就是 2 的 53 次方

    ● 来看下面一个例子

    1. console.log(2 ** 53) // => 9007199254740992
    2. console.log(2 ** 53 + 1) // => 9007199254740992
    3. console.log(2 ** 53 + 2) // => 9007199254740994
    4. console.log(2 ** 53 + 3) // => 9007199254740994
    5. console.log(2 ** 53 + 4// => 9007199254740996

    ● 我们会发现, 对于一些过于大的数字, 把握的不是很准确了, 这就会导致我们的程序出现一些不可控的问题

    ● 在 ES2020 的语法规范中, 提出了一种新的数据结构, 叫做 bigInt 表示大整数, 专门用来处理过大的数字的问题

    ● 在书写的时候也是非常简单的, 只需要在数字的末尾加上一个 n, 那么该数据就表示是一个大整数类型

    const num = 123456789123456789n

    ● 我们需要注意的就是, 大整数类型不能和其他数值类型进行运算

    1. console.log(2n * 3) // => 报错
    2. console.log(2n * 3n// => 6n

    ● 此时我们再来看到之前的例子

    1. console.log(2n ** 53n) // => 9007199254740992n
    2. console.log(2n ** 53n + 1n) // => 9007199254740993n
    3. console.log(2n ** 53n + 2n) // => 9007199254740994n
    4. console.log(2n ** 53n + 3n) // => 9007199254740995n
    5. console.log(2n ** 53n + 4n// => 9007199254740996n

    6.  模块化扩展 : 动态导入

    ● 以前我们的模块化实现规范, 只能是前置导入, 不管一个外部文件, 我们需要用到多少东西, 也不管我们需要在什么时候使用, 那么都需要先完整导入进来再说

    ● ES2020 我们支持了动态导入环境, 尤其是我们结合了 async 和 awiat 语法以后, 变得简单了很多

    ● 语法: import( '地址' )

    ● 例子 :

            ○ utils.js

    1. const add = (a, b) => a + b
    2. export { add }

            ○ index.js

    1. const fn = async () => {
    2. const utils = await import('utils.js')
    3. const res = utils.add(10. 20)
    4. console.log(res) // => 30
    5. }

    ES2021 ( ES12 )

    1.  字符串扩展 : String.prototype.replaceAll()

    ● 语法 : 字符串.replaceAll( 换下字符, 换上字符 )

    ● 作用 : 将所有换下字符全部替换

    1. const str = 'hello world'
    2. const res = str.replaceAll('l', '*')
    3. console.log(res) // => 'he**o wor*d'

    2.  数值分隔符

    ● 在书写数值的时候, 可以以 下划线(_) 作为分隔符书写

    ● 目的就是为了看的时候更直观的看到数字的大小

    const num = 10000000000

            ○ 这个数字是多少呢, 一亿 ? 十亿 ? 一百亿 ?

            ○ 好难一眼看出来

    const num = 10_000_000_000

            ○ 现在呢, 是不是直观了好多

    3.  逻辑运算符的赋值表达式

    ● 以前, 我们的赋值表达式其实有 += -= 之类的内容

    ● 现在只不过是在 ES2021 中, 将 逻辑运算符与赋值表达式合作了

    1. a ||= b
    2. a &&= b
    3. a ??= b

    ● 简单解释一下工作原理

    1. a ||= b
    2. // 等价于 if (!a) a = b
    3. // 当 a 为 假值 的时候, 把 b 的值赋值给 a
    1. a &&= b
    2. // 等价于 if (a) a = b
    3. // 当 a 为 真值 的时候, 把 b 的值赋值给 a
    1. a ??= b
    2. // 等价于 a ?? (a = b)
    3. // 当 a 的值不是 undefined 或者 null 的时候, 把 b 的值赋值给 a

    4.  Promise 扩展 : Promise.any 方法

    ● 是 Promise 的全局静态方法之一, 可以同时放置多个 promise 实例并行执行

    ● 只要任何一个 promise 实例成功了, 那么就返回这个成功的值

    ● 如果所有的 promise 实例都失败了, 那么最终走入失败

    1. const p1 = new Promise( (resolve, reject) => {
    2. setTimeout(() => {
    3. reject('first')
    4. }, 500)
    5. } )
    6. const p2 = new Promise( (resolve, reject) => {
    7. setTimeout(() => {
    8. resolve('second')
    9. }, 500)
    10. } )
    11. const p3 = new Promise( (resolve, reject) => {
    12. setTimeout(() => {
    13. resolve('third')
    14. }, 500)
    15. } )
    16. Promise
    17. .any( [ p1, p2, p3 ] )
    18. .then(res => console.log(' result : ', res))
    19. .catch(err => console.log('失败了 : ', err))
    20. // result : second

    ES2022 ( ES13 )

    1.  类的字段声明

    ● 以前, 我们在书写类的时候, 只能在构造器( constructor ) 内进行字段的声明

    1. class Person {
    2. constructor () {
    3. this.name = '码农键盘上的梦'
    4. this.age = 8
    5. }
    6. }
    7. const p = new Person()
    8. console.log(p.name)
    9. console.log(p.age)

    ● 在 ES2022 中, 我们可以直接在类中定义字段了, 消除了必须要在构造器内定义字段

    1. class Person {
    2. name = '码农键盘上的梦'
    3. age = 8
    4. }
    5. const p = new Person()
    6. console.log(p.name)
    7. console.log(p.age)

    2.  await 运算符扩展

    ● 以前, 我们的 await 运算符必须书写在函数内, 并且函数还有有 async 关键字

    ● 现在, 在 ES2020 的语法规范中, await 关键字可以直接在全局使用了

    1. function ajax() {
    2. return new Promise(() => {
    3. /* ... */
    4. })
    5. }
    6. await ajax()

    3.  数组扩展 : Array.prototype.at() 方法

    ● 语法 : 数组.at( 索引 )

    ● 其实就是通过索引访问数组内某一个数据

    ● 但是比我们的 数组[索引] 更强大一些

    1. const arr = [ 10, 20, 30, 40 ]
    2. // 以前:
    3. console.log(arr[1]) // => 20
    4. // 现在:
    5. console.log(arr.at(1)) // => 20
    6. // 以前:
    7. console.log(arr[arr.length - 2]) // => 30
    8. // 现在:
    9. console.log(arr.at(-2)) // => 30

    4.  数组扩展 : Array.prototype.findLast()和findLastIndex()

    ● 其实和之前的 find() 和 findIndex() 方法用法一样

    ● 只不过是从数组的末尾开始向前检索

    1. const arr = [
    2. { value: 'x', id: 1 },
    3. { value: 'y', id: 2 },
    4. { value: 'z', id: 3 },
    5. { value: 'y', id: 4 },
    6. { value: 'x', id: 5 }
    7. ]
    8. const r1 = arr.find( item => item.value === 'x' )
    9. console.log(r1) // => {value: 'x', id: 1}
    10. const r2 = arr.findLast( item => item.value === 'x' )
    11. console.log(r2) // => {value: 'x', id: 5}
    12. const r3 = arr.findIndex( item => item.value === 'x' )
    13. console.log(r3) // => 0
    14. const r4 = arr.findLastIndex( item => item.value === 'x' )
    15. console.log(r4) // => 4

    5.  正则扩展 : 匹配索引

    以前, 我们在正则匹配的时候, 只能拿到符合要求的字符串片段的开始索引

    现在, 在 ES2022 的语法规范中, 我们可以给正则添加一个 d 修饰符, 来获取到符合要求的字符串片段的开始索引和结束索引

    1. // 以前 :
    2. const str = '你好, 我是码农键盘上的梦, 我今年 8 岁了'
    3. const reg = /码农键盘上的梦/
    4. const res = reg.exec(str)
    5. console.log(res)
    6. /*
    7. 0: "码农键盘上的梦",
    8. groups: undefined,
    9. index: 6,
    10. input: "你好, 我是码农键盘上的梦, 我今年 8 岁了",
    11. length: 1
    12. */
    1. // 现在 :
    2. const str = '你好, 我是码农键盘上的梦, 我今年 8 岁了'
    3. const reg = /码农键盘上的梦/d
    4. const res = reg.exec(str)
    5. console.log(res)
    6. /*
    7. 0: "码农键盘上的梦",
    8. groups: undefined,
    9. index: 6,
    10. indices: [ [ 6, 11 ], groups: undefined ],
    11. input: "你好, 我是码农键盘上的梦, 我今年 8 岁了",
    12. length: 1
    13. */

    ● 我们可以同时拿到这一段字符串的开始索引和结束索引, 分别是 [6] 和 [11]

    ES2023 ( ES14 )

    1.  数组方法扩展 : toReversed() 和 toSorted() 和 toSpliced()

    ● 他们的使用方法和语法于原先的 reverse() sort() splice() 是一样的

    ● 只不过, 原先的方法会直接在原始数组上操作

    ● ES2023 扩展的几个方法, 不会改变原始数组, 而是以返回值的形式返回改变后的数组

    ● 以 toReversed() 为例 :

    1. const arr = [ 10, 20, 30, 40 ]
    2. const res = arr.reverse()
    3. console.log('原始数组 : ', arr) // => [ 40, 30, 20, 10 ]
    4. console.log('返回值 : ', res) // => [ 40, 30, 20, 10 ]
    1. const arr = [ 10, 20, 30, 40 ]
    2. const res = arr.toReversed()
    3. console.log('原始数组 : ', arr) // => [ 10, 20, 30, 40 ]
    4. console.log('返回值 : ', res) // => [ 40, 30, 20, 10 ]

    ● 其他的方法和 toReversed() 方法是一个道理

    2.  其他

    ● ES2023 还在计划引入一些新的内容

    管道操作符 |>

    Record

    tuple

    Iteration Helpers

    Better Intl Support

    ● 只不过目前还处在计划中

    ● 等到彻底发布了, 浏览器也可以支持了, 我会再次更新, 给大家分享最新的技术点

  • 相关阅读:
    Django自动生成docs接口文档
    踩坑,发现一个ShardingJdbc读写分离的BUG
    android12将wifi功能和移动数据功能从一个网络按钮分开
    Docker基础管理
    docker启动mysql8目录挂载改动
    LPL Ban/Pick 选人阶段的遮罩效果是如何实现的?
    如何使用 mail 指令在命令行发送邮件
    SpringBoot中使用XJar进行JAR安全加密运行同时支持原生JAR
    计算机系统基础期末复习
    4.力扣c++刷题-->删除有序数组中的重复项 II
  • 原文地址:https://blog.csdn.net/qq_44848480/article/details/133749619