Ecma International 负责对 JavaScript 的标准化。是他们制定了 ECMAScript 规范。当提到 ECMAScript 时,基本上可以把它看作是 JavaScript 的同义词。从 2015 年开始,开始用年份标记版本,即 ECMAScript 2015 缩写为 ES2015。但是也会使用版本号的计数,所以 ES6 与 ES2015 相同。尚未发布的功能被称为 ESNext。
ECMAScript 2020/ES2020/ES11 于 6 月发布,并且已经在现代浏览器中实现。让我们看看这会带来什么好处。
太长不看版
如果你不想看细节,那么只看这张图就够了。
空值合并
如果你在赋值时想要一个默认值(如果它为 null
或 undefined
),则可以使用 ??
。
const name = person.fullName ?? 'anonymous';
如果对象 person
没有 fullName
值,则 name
将被赋值为 “anonymous”。如果 person 的 fullName
有值,则把该值赋值给变量 name
。
你可能认为用 ||
就能做到。但这几乎是几乎相同的,如果 ||
前面的值是虚值,那么这个表达式将不会短路,并且会使用后面的值。但是请记住,空字符串 ''
,0
,NaN
和 false
都是虚值,在这些情况下将使用默认值,如果我们要用这些进行赋值的话,就行不通了。??
则只检查 null
和 undefined
。
const user = { preferredSound: 0 }
let sound = user.preferredSound ?? 50 // value is 0
let soundWrong = user.preferredSound || 50 // value is 50
仅当 preferredSound
为 undefined
或者 null
时才使用 50 这个值。
可选链
如果要使用多级嵌套在对象中的属性,在以前必须要检查它们是否为 null
或 undefined
,以避免代码崩溃。现在可以在访问这些属性之前使用 ?.
,这样就可以只有在值不为 null
或 undefined
时使用 ?.
后面的代码。
例如:
代码语言:javascript复制const house = { owner: { name: 'Jim', pet: null }};// Old JavaScript
if(house && house.owner && house.owner.pet && house.owner.pet.type === 'dog'){
console.log('owner has a dog');
}// ES2020
if (house?.owner?.pet?.type === 'dog') {
console.log('owner has a dog');
}
Promise.allSettled
如果要执行更多的异步请求,可以使用 Promise.all
来收集它们。但是如果其中任何一个请求失败的话,将会引发异常。如果我们希望每个请求都能够完成,无论其请求是否失败,那该怎么办。这时可以用 Promise.allSettled
,当所有请求都被解决或拒绝时,它将返回。
const promises = [Promise.resolve(1), Promise.reject(2)];
const [result1, result2] = await Promise.allSettled(promises);
即使其他 promise 被拒绝了,我们仍然可以在这里使用 result1
的值。
matchAll
如果要用正则表达式查找所有的匹配项,可以用 match
来得到所有子字符串。但是,如果你既需要子字符串又需要索引,该怎么办?这时可以用 matchAll
并进行重复匹配。
例如找到一个字符串中的所有数字:
代码语言:javascript复制const matches = 'Here are some numbers: 5 12 88'.matchAll(/d /g);
for (const match of matches) {
console.log(match);
}// 输出:
// ["5", index: 22, input: "Here are some numbers: 5 12 88", groups: undefined]
// ["12", index: 24, input: "Here are some numbers: 5 12 88", groups: undefined]
// ["88", index: 27, input: "Here are some numbers: 5 12 88", groups: undefined]
BigInt
BigInt
是 JavaScript 中新的原始数据类型,与 Boolean
、Number
、String
、Symbol
和 undefined
的地位相同。BigInt
可以安全的处理大于 Number
限制的整数数字。也就是说如果要处理大于 9007199254740991
的数字时应该用 BigInt
。BigInt
在数字末尾用 n 表示。
9_007_199_254_740_991 2; // 9007199254740992
BigInt(9_007_199_254_740_991) BigInt(2) // 9007199254740993n
动态导入
以前只能在文件开头静态导入模块。现在有了动态导入,可以按需在代码中的任何位置进行这种操作。import()
会与模块一起返回一个 Promise。
const module = await import('module');
模块命名空间导出
在大多数情况下,我们能够通过导入导出 JavaScript 模块来重命名模块的名称,就像这样:
代码语言:javascript复制import * as values from 'module';
import { value as v } from 'module';export { v as value };
但是没有办法直接从名称被更改的另一个模块中重新导出某些内容。现在有了 ES2020,则可以这样做:
代码语言:javascript复制export * as someUtils from 'utils';
globalThis
如果你的代码需要在多个环境(例如浏览器和 Node 服务器)下运行,那么它们所使用全局对象名称并不一致。在浏览器中用的是 window
,Node 则用的是 global
,而 web worker 用的是self
。现在,无论代码在哪种环境中运行,globalThis
都能够为你提供正确的全局对象。
下面是一个例子,我们需要检查是否可以向用户提示 alert。如果代码在浏览器中运行,则 globalThis
将会引用 window,并且 alert 也可以使用。
if (typeof globalThis.alert === 'function'){
globalThis.alert('hi');
}