ES 新特性九年速览:从 ES2016 到 ES2024
2026/6/11 14:02:18 网站建设 项目流程

文章目录

  • 前言
  • 一、ES2016
    • 1.1 Array.prototype.includes
    • 1.2 指数运算符
  • 二、ES2017
    • 2.1 async / await
    • 2.2 Object.entries / Object.values
    • 2.3 String.prototype.padStart / padEnd
    • 2.4 函数参数尾逗号
  • 三、ES2018
    • 3.1 Rest / Spread 属性
    • 3.2 Promise.prototype.finally
    • 3.3 异步迭代
  • 四、ES2019
    • 4.1 Array.prototype.flat / flatMap
    • 4.2 Object.fromEntries
    • 4.3 可选的 catch 绑定
  • 五、ES2020
    • 5.1 可选链操作符 ?.
    • 5.2 空值合并操作符 ??
    • 5.3 BigInt
    • 5.4 globalThis
    • 5.5 Promise.allSettled
    • 5.6 顶层 await
  • 六、ES2021
    • 6.1 String.prototype.replaceAll
    • 6.2 Promise.any
    • 6.3 逻辑赋值运算符
    • 6.4 数值分隔符
  • 七、ES2022
    • 7.1 Object.hasOwn
    • 7.2 Array.prototype.at
    • 7.3 class 私有属性和方法
    • 7.4 Error.cause
  • 八、ES2023
    • 8.1 Array 的非破坏性方法
  • 九、ES2024
    • 9.1 Object.groupBy / Map.groupBy
    • 9.2 Promise.withResolvers
  • 十、面试聚焦
    • 10.1 ?? vs || 的区别
    • 10.2 顶层 await 的条件
  • 十一、易混淆点
  • 十二、思考与练习
  • 总结

前言

ES2016(ES7)到 ES2024(ES15)引入了大量实用特性,掌握这些新特性能让代码更简洁、更安全。本篇速览各版本的重要更新。


一、ES2016

1.1 Array.prototype.includes

constarr=[1,2,3,NaN]// indexOf 无法正确判断 NaNarr.indexOf(NaN)// -1// includes 可以正确判断 NaNarr.includes(NaN)// truearr.includes(2)// truearr.includes(4)// false

1.2 指数运算符

// 之前Math.pow(2,10)// 1024// ES20162**10// 1024// 结合赋值letx=2x**=3// x = x ** 3 = 8

二、ES2017

2.1 async / await

// 之前:Promise 链functionfetchData(){returnfetch('/api/user').then(res=>res.json()).then(user=>fetch(`/api/posts/${user.id}`)).then(res=>res.json())}// ES2017:async/awaitasyncfunctionfetchData(){constres=awaitfetch('/api/user')constuser=awaitres.json()constpostsRes=awaitfetch(`/api/posts/${user.id}`)returnpostsRes.json()}// 错误处理asyncfunctionsafeFetch(url){try{constres=awaitfetch(url)returnawaitres.json()}catch(err){console.error('请求失败:',err.message)returnnull}}

2.2 Object.entries / Object.values

constobj={a:1,b:2,c:3}// Object.entries:返回键值对数组Object.entries(obj)// [['a', 1], ['b', 2], ['c', 3]]// Object.values:返回值数组Object.values(obj)// [1, 2, 3]// 配合 for...of 遍历for(const[key,value]ofObject.entries(obj)){console.log(key,value)}

2.3 String.prototype.padStart / padEnd

// 补齐字符串长度'5'.padStart(2,'0')// '05''hello'.padEnd(10,'!')// 'hello!!!!!'// 常用于格式化consttime='9'`${time.padStart(2,'0')}:00`// '09:00'

2.4 函数参数尾逗号

// 允许函数参数列表末尾有逗号functionadd(a,b,// 尾逗号,方便添加新参数){returna+b}

三、ES2018

3.1 Rest / Spread 属性

// Rest 属性const{a,...rest}={a:1,b:2,c:3}// a = 1, rest = { b: 2, c: 3 }// Spread 属性constmerged={a:1,...{b:2,c:3}}// { a: 1, b: 2, c: 3 }

3.2 Promise.prototype.finally

fetch('/api/data').then(res=>res.json()).then(data=>console.log(data)).catch(err=>console.error(err)).finally(()=>{// 无论成功或失败都会执行hideLoading()})

3.3 异步迭代

// for await...ofasyncfunction*asyncGenerator(){yieldawaitPromise.resolve(1)yieldawaitPromise.resolve(2)yieldawaitPromise.resolve(3)}forawait(constvalueofasyncGenerator()){console.log(value)// 1, 2, 3}

四、ES2019

4.1 Array.prototype.flat / flatMap

constarr=[1,[2,3],[4,[5,6]]]// flat:扁平化数组arr.flat()// [1, 2, 3, 4, [5, 6]]arr.flat(2)// [1, 2, 3, 4, 5, 6]arr.flat(Infinity)// 完全扁平化// flatMap:先 map 再 flatconstarr2=[1,2,3]arr2.flatMap(x=>[x,x*2])// [1, 2, 2, 4, 3, 6]

4.2 Object.fromEntries

// Object.entries 的逆操作constentries=[['a',1],['b',2]]Object.fromEntries(entries)// { a: 1, b: 2 }// 常用于转换 URL 参数consturl=newURLSearchParams('foo=1&bar=2')Object.fromEntries(url)// { foo: '1', bar: '2' }

4.3 可选的 catch 绑定

// 之前:必须有 catch 参数try{JSON.parse('invalid')}catch(e){// 必须写 e,即使不使用}// ES2019:可以省略 catch 参数try{JSON.parse('invalid')}catch{// 不需要写参数}

五、ES2020

5.1 可选链操作符 ?.

constuser={address:{street:'Main St'}}// 之前:需要层层判断conststreet=user&&user.address&&user.address.street// ES2020:可选链conststreet=user?.address?.street// 调用方法user?.getName?.()// 访问数组元素arr?.[0]

5.2 空值合并操作符 ??

constvalue=null??'default'// 'default'constvalue2=0??'default'// 0constvalue3=''??'default'// ''// 与 || 的区别constvalue4=0||'default'// 'default'(0 是 falsy)constvalue5=0??'default'// 0(只判断 null/undefined)// ?? 只判断 null 和 undefined// || 判断所有 falsy 值(0, '', false, null, undefined, NaN)

5.3 BigInt

// 超大整数constmax=Number.MAX_SAFE_INTEGER// 9007199254740991constbig=9007199254740991n// BigIntconstbig2=BigInt(9007199254740991)// 运算constsum=big+1n// 9007199254740992n// 注意:BigInt 和 Number 不能混合运算// const result = big + 1 // TypeError

5.4 globalThis

// 获取全局对象的统一方式// 浏览器是 window,Node.js 是 global,Web Worker 是 selfglobalThis// 统一的全局对象

5.5 Promise.allSettled

constpromises=[Promise.resolve(1),Promise.reject('error'),Promise.resolve(3)]// Promise.all:任一 reject 就立即 rejectPromise.all(promises)// reject 'error'// Promise.allSettled:等待所有完成Promise.allSettled(promises)// [// { status: 'fulfilled', value: 1 },// { status: 'rejected', reason: 'error' },// { status: 'fulfilled', value: 3 }// ]

5.6 顶层 await

// 在模块顶层可以使用 awaitconstresponse=awaitfetch('/api/data')constdata=awaitresponse.json()// 限制:只能在 ES 模块中使用(type="module" 或 .mjs)

六、ES2021

6.1 String.prototype.replaceAll

conststr='aabbcc'// 之前:正则str.replace(/a/g,'x')// 'xxbbcc'// ES2021str.replaceAll('a','x')// 'xxbbcc'

6.2 Promise.any

constpromises=[Promise.reject('error1'),Promise.reject('error2'),Promise.resolve(3)]// 任一 resolve 就 resolvePromise.any(promises)// resolve 3// 全部 reject 才 reject// AggregateError: All promises were rejected

6.3 逻辑赋值运算符

// &&=a&&=b// 等价于 a && (a = b)// ||=a||=b// 等价于 a || (a = b)// ??=a??=b// 等价于 a ?? (a = b)// 示例letconfig={}config.timeout??=3000// 如果 timeout 是 null/undefined,则设置为 3000

6.4 数值分隔符

// 提高大数字的可读性constbillion=1_000_000_000constbytes=0xFF_FF_FF_FFconstfraction=0.123_456_789// 分隔符不影响数值1_000===1000// true

七、ES2022

7.1 Object.hasOwn

constobj={a:1}// 之前:hasOwnPropertyobj.hasOwnProperty('a')// true// ES2022:Object.hasOwn(推荐)Object.hasOwn(obj,'a')// true// 优势:即使对象没有继承 Object.prototype 也能用constobj2=Object.create(null)obj2.a=1obj2.hasOwnProperty('a')// TypeErrorObject.hasOwn(obj2,'a')// true

7.2 Array.prototype.at

constarr=[1,2,3,4,5]// 之前:获取最后一个元素arr[arr.length-1]// 5arr.slice(-1)[0]// 5// ES2022:at()arr.at(-1)// 5arr.at(0)// 1arr.at(-2)// 4

7.3 class 私有属性和方法

classCounter{// 私有属性#count=0// 静态私有属性static#total=0// 私有方法#increment(){this.#count++}increment(){this.#increment()Counter.#total++}getcount(){returnthis.#count}}

7.4 Error.cause

try{try{JSON.parse('invalid')}catch(err){thrownewError('Parse failed',{cause:err})}}catch(err){console.log(err.message)// 'Parse failed'console.log(err.cause.message)// 'Unexpected token...'}

八、ES2023

8.1 Array 的非破坏性方法

constarr=[3,1,2]// toSorted:非破坏性排序arr.toSorted()// [1, 2, 3],原数组不变arr// [3, 1, 2]// toReversed:非破坏性反转arr.toReversed()// [2, 1, 3],原数组不变// toSpliced:非破坏性 splicearr.toSpliced(1,1)// [3, 2],原数组不变// with:非破坏性修改指定位置arr.with(0,10)// [10, 1, 2],原数组不变

九、ES2024

9.1 Object.groupBy / Map.groupBy

constpeople=[{name:'Alice',age:25},{name:'Bob',age:30},{name:'Charlie',age:25}]// 按年龄分组constgrouped=Object.groupBy(people,p=>p.age)// {// 25: [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 25 }],// 30: [{ name: 'Bob', age: 30 }]// }

9.2 Promise.withResolvers

// 之前:需要在外部定义 resolve/rejectletresolve,rejectconstpromise=newPromise((res,rej)=>{resolve=res reject=rej})// ES2024const{promise,resolve,reject}=Promise.withResolvers()

十、面试聚焦

10.1 ?? vs || 的区别

// || 判断所有 falsy 值0||'default'// 'default'''||'default'// 'default'false||'default'// 'default'null||'default'// 'default'// ?? 只判断 null 和 undefined0??'default'// 0''??'default'// ''false??'default'// falsenull??'default'// 'default'

10.2 顶层 await 的条件

// 只能在 ES 模块中使用顶层 await// 1. <script type="module">// 2. .mjs 文件// 3. package.json 中 "type": "module"// CommonJS 模块中不能使用// 顶层 await 会阻塞当前模块的加载

十一、易混淆点

  1. ?? vs ||??只判断null/undefined||判断所有 falsy 值(0, ‘’, false 等)。
  2. ?. 的短路特性a?.b.c中如果a是 null/undefined,b.c不会执行。
  3. 顶层 await:只能在 ES 模块中使用,会阻塞当前模块的加载。
  4. Object.hasOwn vs hasOwnPropertyObject.hasOwn更安全,即使对象没有继承Object.prototype也能用。
  5. ES2023 非破坏性方法toSortedtoReversed等返回新数组,不修改原数组。

十二、思考与练习

1.0 ?? 'default'0 || 'default'的结果分别是什么?为什么?

解析:

  • 0 ?? 'default'0(?? 只判断 null/undefined)
  • 0 || 'default''default'(|| 判断所有 falsy 值,0 是 falsy)

2.什么是顶层 await?有什么限制?

解析:

  • 顶层 await 允许在模块顶层使用 await,无需包裹在 async 函数中
  • 限制:只能在 ES 模块中使用(<script type="module">.mjs

3.Object.hasOwnhasOwnProperty好在哪里?

解析:

  • hasOwnProperty依赖原型链,如果对象没有继承Object.prototype会报错
  • Object.hasOwn是静态方法,不依赖原型链,更安全

4.Array.prototype.at(-1)的作用是什么?

解析:获取数组的最后一个元素,等价于arr[arr.length - 1],但更简洁,支持负索引。

5.ES2023 的toSortedsort有什么区别?

解析:

  • sort()是破坏性的,会修改原数组
  • toSorted()是非破坏性的,返回新数组,原数组不变

总结

  • ES2016includes**指数运算符
  • ES2017async/awaitObject.entries/valuespadStart/padEnd
  • ES2018:Rest/Spread 属性、Promise.finally、异步迭代
  • ES2019flat/flatMapObject.fromEntries、可选 catch 绑定
  • ES2020?.可选链、??空值合并、BigIntglobalThisPromise.allSettled、顶层 await
  • ES2021replaceAllPromise.any、逻辑赋值运算符、数值分隔符
  • ES2022Object.hasOwnat()、class 私有属性/方法、Error.cause
  • ES2023toSorted/toReversed/toSpliced/with非破坏性方法
  • ES2024Object.groupByPromise.withResolvers

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询