ES 新特性九年速览:从 ES2016 到 ES2024

发布时间:2026/6/11 14:02:22

ES 新特性九年速览:从 ES2016 到 ES2024 文章目录前言一、ES20161.1 Array.prototype.includes1.2 指数运算符二、ES20172.1 async / await2.2 Object.entries / Object.values2.3 String.prototype.padStart / padEnd2.4 函数参数尾逗号三、ES20183.1 Rest / Spread 属性3.2 Promise.prototype.finally3.3 异步迭代四、ES20194.1 Array.prototype.flat / flatMap4.2 Object.fromEntries4.3 可选的 catch 绑定五、ES20205.1 可选链操作符 ?.5.2 空值合并操作符 ??5.3 BigInt5.4 globalThis5.5 Promise.allSettled5.6 顶层 await六、ES20216.1 String.prototype.replaceAll6.2 Promise.any6.3 逻辑赋值运算符6.4 数值分隔符七、ES20227.1 Object.hasOwn7.2 Array.prototype.at7.3 class 私有属性和方法7.4 Error.cause八、ES20238.1 Array 的非破坏性方法九、ES20249.1 Object.groupBy / Map.groupBy9.2 Promise.withResolvers十、面试聚焦10.1 ?? vs || 的区别10.2 顶层 await 的条件十一、易混淆点十二、思考与练习总结前言ES2016ES7到 ES2024ES15引入了大量实用特性掌握这些新特性能让代码更简洁、更安全。本篇速览各版本的重要更新。一、ES20161.1 Array.prototype.includesconstarr[1,2,3,NaN]// indexOf 无法正确判断 NaNarr.indexOf(NaN)// -1// includes 可以正确判断 NaNarr.includes(NaN)// truearr.includes(2)// truearr.includes(4)// false1.2 指数运算符// 之前Math.pow(2,10)// 1024// ES20162**10// 1024// 结合赋值letx2x**3// x x ** 3 8二、ES20172.1 async / await// 之前Promise 链functionfetchData(){returnfetch(/api/user).then(resres.json()).then(userfetch(/api/posts/${user.id})).then(resres.json())}// ES2017async/awaitasyncfunctionfetchData(){constresawaitfetch(/api/user)constuserawaitres.json()constpostsResawaitfetch(/api/posts/${user.id})returnpostsRes.json()}// 错误处理asyncfunctionsafeFetch(url){try{constresawaitfetch(url)returnawaitres.json()}catch(err){console.error(请求失败:,err.message)returnnull}}2.2 Object.entries / Object.valuesconstobj{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)// 05hello.padEnd(10,!)// hello!!!!!// 常用于格式化consttime9${time.padStart(2,0)}:00// 09:002.4 函数参数尾逗号// 允许函数参数列表末尾有逗号functionadd(a,b,// 尾逗号方便添加新参数){returnab}三、ES20183.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.finallyfetch(/api/data).then(resres.json()).then(dataconsole.log(data)).catch(errconsole.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}四、ES20194.1 Array.prototype.flat / flatMapconstarr[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 参数consturlnewURLSearchParams(foo1bar2)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{// 不需要写参数}五、ES20205.1 可选链操作符 ?.constuser{address:{street:Main St}}// 之前需要层层判断conststreetuseruser.addressuser.address.street// ES2020可选链conststreetuser?.address?.street// 调用方法user?.getName?.()// 访问数组元素arr?.[0]5.2 空值合并操作符 ??constvaluenull??default// defaultconstvalue20??default// 0constvalue3??default// // 与 || 的区别constvalue40||default// default0 是 falsyconstvalue50??default// 0只判断 null/undefined// ?? 只判断 null 和 undefined// || 判断所有 falsy 值0, , false, null, undefined, NaN5.3 BigInt// 超大整数constmaxNumber.MAX_SAFE_INTEGER// 9007199254740991constbig9007199254740991n// BigIntconstbig2BigInt(9007199254740991)// 运算constsumbig1n// 9007199254740992n// 注意BigInt 和 Number 不能混合运算// const result big 1 // TypeError5.4 globalThis// 获取全局对象的统一方式// 浏览器是 windowNode.js 是 globalWeb Worker 是 selfglobalThis// 统一的全局对象5.5 Promise.allSettledconstpromises[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// 在模块顶层可以使用 awaitconstresponseawaitfetch(/api/data)constdataawaitresponse.json()// 限制只能在 ES 模块中使用typemodule 或 .mjs六、ES20216.1 String.prototype.replaceAllconststraabbcc// 之前正则str.replace(/a/g,x)// xxbbcc// ES2021str.replaceAll(a,x)// xxbbcc6.2 Promise.anyconstpromises[Promise.reject(error1),Promise.reject(error2),Promise.resolve(3)]// 任一 resolve 就 resolvePromise.any(promises)// resolve 3// 全部 reject 才 reject// AggregateError: All promises were rejected6.3 逻辑赋值运算符// ab// 等价于 a (a b)// ||a||b// 等价于 a || (a b)// ??a??b// 等价于 a ?? (a b)// 示例letconfig{}config.timeout??3000// 如果 timeout 是 null/undefined则设置为 30006.4 数值分隔符// 提高大数字的可读性constbillion1_000_000_000constbytes0xFF_FF_FF_FFconstfraction0.123_456_789// 分隔符不影响数值1_0001000// true七、ES20227.1 Object.hasOwnconstobj{a:1}// 之前hasOwnPropertyobj.hasOwnProperty(a)// true// ES2022Object.hasOwn推荐Object.hasOwn(obj,a)// true// 优势即使对象没有继承 Object.prototype 也能用constobj2Object.create(null)obj2.a1obj2.hasOwnProperty(a)// TypeErrorObject.hasOwn(obj2,a)// true7.2 Array.prototype.atconstarr[1,2,3,4,5]// 之前获取最后一个元素arr[arr.length-1]// 5arr.slice(-1)[0]// 5// ES2022at()arr.at(-1)// 5arr.at(0)// 1arr.at(-2)// 47.3 class 私有属性和方法classCounter{// 私有属性#count0// 静态私有属性static#total0// 私有方法#increment(){this.#count}increment(){this.#increment()Counter.#total}getcount(){returnthis.#count}}7.4 Error.causetry{try{JSON.parse(invalid)}catch(err){thrownewError(Parse failed,{cause:err})}}catch(err){console.log(err.message)// Parse failedconsole.log(err.cause.message)// Unexpected token...}八、ES20238.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]原数组不变九、ES20249.1 Object.groupBy / Map.groupByconstpeople[{name:Alice,age:25},{name:Bob,age:30},{name:Charlie,age:25}]// 按年龄分组constgroupedObject.groupBy(people,pp.age)// {// 25: [{ name: Alice, age: 25 }, { name: Charlie, age: 25 }],// 30: [{ name: Bob, age: 30 }]// }9.2 Promise.withResolvers// 之前需要在外部定义 resolve/rejectletresolve,rejectconstpromisenewPromise((res,rej){resolveres rejectrej})// ES2024const{promise,resolve,reject}Promise.withResolvers()十、面试聚焦10.1 ?? vs || 的区别// || 判断所有 falsy 值0||default// default||default// defaultfalse||default// defaultnull||default// default// ?? 只判断 null 和 undefined0??default// 0??default// false??default// falsenull??default// default10.2 顶层 await 的条件// 只能在 ES 模块中使用顶层 await// 1. script typemodule// 2. .mjs 文件// 3. package.json 中 type: module// CommonJS 模块中不能使用// 顶层 await 会阻塞当前模块的加载十一、易混淆点?? vs ||??只判断null/undefined||判断所有 falsy 值0, ‘’, false 等。?. 的短路特性a?.b.c中如果a是 null/undefinedb.c不会执行。顶层 await只能在 ES 模块中使用会阻塞当前模块的加载。Object.hasOwn vs hasOwnPropertyObject.hasOwn更安全即使对象没有继承Object.prototype也能用。ES2023 非破坏性方法toSorted、toReversed等返回新数组不修改原数组。十二、思考与练习1.0 ?? default和0 || default的结果分别是什么为什么解析0 ?? default→0?? 只判断 null/undefined0 || default→default|| 判断所有 falsy 值0 是 falsy2.什么是顶层 await有什么限制解析顶层 await 允许在模块顶层使用 await无需包裹在 async 函数中限制只能在 ES 模块中使用script typemodule或.mjs3.Object.hasOwn比hasOwnProperty好在哪里解析hasOwnProperty依赖原型链如果对象没有继承Object.prototype会报错Object.hasOwn是静态方法不依赖原型链更安全4.Array.prototype.at(-1)的作用是什么解析获取数组的最后一个元素等价于arr[arr.length - 1]但更简洁支持负索引。5.ES2023 的toSorted和sort有什么区别解析sort()是破坏性的会修改原数组toSorted()是非破坏性的返回新数组原数组不变总结ES2016includes、**指数运算符ES2017async/await、Object.entries/values、padStart/padEndES2018Rest/Spread 属性、Promise.finally、异步迭代ES2019flat/flatMap、Object.fromEntries、可选 catch 绑定ES2020?.可选链、??空值合并、BigInt、globalThis、Promise.allSettled、顶层 awaitES2021replaceAll、Promise.any、逻辑赋值运算符、数值分隔符ES2022Object.hasOwn、at()、class 私有属性/方法、Error.causeES2023toSorted/toReversed/toSpliced/with非破坏性方法ES2024Object.groupBy、Promise.withResolvers

相关新闻