JavaScript 中的新功能 - ES2020
2020 年 6 月,JavaScript 语言推出了一些新功能。
TLDR——太长,没读
如果您不想阅读整篇文章,我已经在这张图片中收集了最值得注意的内容。
背景
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,则名称将为“anonymous”。如果 Person 对象的 fullName 有值,则该值将被写入变量 name。
你可能会认为这一直是用 就能做到的||
。但这几乎是一样的,如果前一个值为||
假,求值不会短路,而是使用下一个值。但请记住,空字符串''
、0
、NaN
和false
都是假的,会使用默认值,如果我们想赋值这些值,这可能是我们不希望看到的。因此,??
我们使用 nullish 来代替,它只检查null
或undefined
。
const user = { preferredSound: 0 }
let sound = user.preferredSound ?? 50 // value is 0
let soundWrong = user.preferredSound || 50 // value is 50
仅当 preferredSound 未设置或为空时才使用 50,应该可以将声音级别设置为零。
可选链式调用
如果要使用对象中嵌套多层的属性,以前必须检查它们是否为null
或 ,undefined
以免代码崩溃。现在我们可以在访问这些属性之前使用 ,这样只有当值不是或 时,?.
才会使用之后的代码。null
undefined
想象一下,我们有一栋房子,它有一个主人,主人又养了一只宠物。这时,我们需要确保房子、主人或宠物有值,或者提前检查它们,以避免出现“无法读取 null 的‘type’属性”的错误。您可以在这里看到 ES2020 之前和之后我们是如何处理这个问题的。
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);
即使其他承诺被拒绝,我们仍然可以使用 result1 值。
匹配全部
如果要使用 regex 查找正则表达式匹配的所有实例,可以使用match
来获取所有子字符串。但是,如果您同时想要子字符串和索引怎么办?那么您可以使用matchAll
并迭代匹配项。
让我们找出字符串中的所有数字。
const matches = 'Here are some numbers: 5 12 88'.matchAll(/\d+/g);
for (const match of matches) {
console.log(match);
}
// Output:
// ["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
。这意味着如果我们要处理大于 9_007_199_254_740_991 的数字,最好使用BigInt
。BigInt
用数字末尾的 n 表示。
我们将数字 9_007_199_254_740_991 加 2,正确的数字应该以数字 3 结尾。
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 模块的导入和导出,我们在大多数情况下能够重命名模块的名称。就像这样。
import * as values from 'module';
import { value as v } from 'module';
export { v as value };
但是我们之前无法直接从另一个模块中重新导出名称更改的内容。现在有了 ES2020,我们可以这样做:
export * as someUtils from 'utils';
globalThis
如果您编写的代码在多个环境中运行,例如浏览器和 Node 服务器,那么它们的全局对象会有不同的名称。浏览器使用window
,Node 使用global
,而 Web Worker 使用self
。现在,globalThis
无论代码在哪个环境中运行,都会返回正确的全局对象。
下面是一个示例,我们想检查是否可以向用户提示警告。如果代码在浏览器中运行,它将globalThis
引用窗口,并且警告可用。
if (typeof globalThis.alert === 'function'){
globalThis.alert('hi');
}