title: ES2020/2021 author: Gamehu tags: - 前端 categories: - 学习 date: 2021-07-09 10:42:00 --- ### 背景 今天看阮老师的科技周刊的时候,里头提到了ES2021(作者默认所有的提案最终都会被通过),正好借此梳理一下,ES2020和ES2021,个人使用过的以及后续可能会使用的一些功能,所以这篇不是科普类型,纯属个人喜好的记录。 ### 开始 ##### 空值合并运算符:?? > **??**是一个逻辑操作符,当左侧的操作数为 [`null`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/null) 或者 [`undefined`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined) 时,则返回右侧操作数,否则返回左侧操作数。所以该运算符完美适配默认值的场景。 ```javascript const foo = null ?? 'default string'; console.log(foo); // expected output: "default string" const baz = 0 ?? 42; console.log(baz); // expected output: 0 ``` 多说一句: > 设置默认值以前常用的是:**||**(逻辑或操作符),但是都知道不用用它作为有false和0的情况(因为||**判断时,会把值转换为布尔值,而false和0转为布尔值时都是false,所以对于数字类型和布尔类型的用||设置默认值是不合理的+) ##### 可选的链接运算符:?. > 嵌套对象时特别好用。表达式还短。 > > 如果引用为空(null 或 undefined),则表达式会短路返回 undefined。 ```javascript if( a && a.b && a.b.c){ //do something... } //可换成: if( a?.b?c){ //do something... } const a={} const test=a?.b?.c // expected output: undefined ``` ##### Promise.any() and AggregateError `Promise.any()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成`fulfilled`状态,包装实例就会变成`fulfilled`状态;如果所有参数实例都变成`rejected`状态,包装实例就会变成`rejected`状态 [阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版](https://www.bookstack.cn/read/es6-3rd/spilt.9.docs-promise.md) [Promise.race和Promise.any](https://stackoverflow.com/questions/61732049/what-is-the-difference-between-promise-any-and-promise-race) `Promise.any()`跟`Promise.race()`方法很像,只有一点不同,就是不会因为某个 Promise 变成`rejected`状态而结束。 ```javascript Promise.race([ new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')), new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')), new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')), ]) .then(value => console.log(`Result: ${value}`)) .catch (err => console.log(err)) // expected output: Third Promise.any([ new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')), new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')), new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')), ]) .then(value => console.log(`Result: ${value}`)) .catch (err => console.log(err)) // expected output: Second ``` ##### globalThis 全局属性 [`globalThis`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis) 包含全局的 `this` 值,类似于全局对象(global object)。`globalThis` 提供了一个标准的方式来获取不同环境下的全局 `this` 对象(也就是全局对象自身)不用在考虑不同的环境获取方式不一样的问题。 ##### String replaceAll() ``` const newStr = str.replaceAll(regexp|substr, newSubstr|function). // 当使用一个 `regex`时,您必须设置全局(“ g”)标志 ``` **`replaceAll(pattern,replacement)`** 方法返回一个新字符串,新字符串所有满足 `pattern` 的部分都已被`replacement` 替换。`pattern`可以是一个字符串或一个 [`RegExp`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp), `replacement`可以是一个字符串或一个在每次匹配被调用的函数。 **old:** ```javascript const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫"; const newStr = str.replace("is", "isn't"); console.log(newStr); // expected output:zhangsan isn't wangmazi's 舅子,wangmazi is zhangsan's 妹夫 // 替换所有,只能用正则 const newStr = str.replace(/is/g, "isn't"); console.log(newStr); //expected output: zhangsan isn't wangmazi's 舅子,wangmazi isn't zhangsan's 妹夫 ``` **new:** ```javascript const str = "zhangsan is wangmazi's 舅子,wangmazi is zhangsan's 妹夫"; const newStr = str.replaceAll("is", "isn't"); console.log(newStr); // expected output: zhangsan isn't wangmazi's 舅子,wangmazi isn't zhangsan's 妹夫 ``` ##### 逻辑赋值运算符:(&&= ||= ??=) ```javascript x ||= y; // 等同 x || (x = y); x &&= y; // 等同 x && (x = y); // 或者 if(x) { x = y } x ??= y; // 等同 x ?? (x = y); // 比如 let x = 1; let y = 2; x &&= y; console.log(x); //expected output: 2 ``` ##### 下划线作为数字分隔符 ```javascript const billion = 1000_000_000; console.log(billion); //expected output:1000000000 const trillion = 1000_000_000_000n; console.log(trillion.toString()); //expected output: "1000000000000" console.log(1000_000_000 === 1000000000); //expected output: true ``` [了解更多](https://backbencher.dev/javascript/numeric-separators) ##### Promise.allSettled 我通常在页面初始化需要多个数据且相互之间又没联系的时候会用它。 > **Promise.allSettled()**方法接受一组Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果(不管是`fulfilled`还是`rejected`),返回结果是一个对象数组,每个对象表示对应的promise结果。 > > 当有多个彼此不依赖的异步任务成功完成时,或者我们不关心异步操作的结果,只关心每个`promise`的结果时,通常使用它。 ```javascript const p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000,'failed')); const p2 = new Promise((resolve, reject) => setTimeout(reject, 2000,'a')); const p3 = new Promise((resolve, reject) => setTimeout(resolve, 3000,'b')); // 返回值对象:fulfilled时,对象有value属性,rejected时有reason属性 Promise.allSettled([p1, p2, p3]).then(values => console.log(values)); //expected output: Array // 0: {status: "fulfilled", value: "failed"} // 1: {status: "rejected", reason: "a"} // 2: {status: "fulfilled", value: "b"} ``` > 相比之下,`Promise.all()` 更适合彼此相互依赖或者在其中任何一个`reject`时就需要立即结束的场景。即`Promise.all()` 其实无法确定所有请求都结束。 #### 参考资料: https://github.com/tc39/ecma262/releases https://backbencher.dev/javascript/es2021-new-features https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247494289&idx=2&sn=d8a0ef1443954b7a5bae79ec90411cbd&chksm=f9525fd2ce25d6c4f1d1ac2ab8ce6b7034f68f484881a3548549648dfe5aedd427c7b930385b&scene=21#wechat_redirect https://tc39.es/ecma262/2021/#sec-web-scripting https://www.telerik.com/blogs/learn-new-features-introduced-javascript-es2021 https://blog.fundebug.com/2019/08/28/javascript-nullish-coalescing/ `本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。`