你应该尝试的 7 个 JavaScript ES2020 特性
ES2020规范带来了许多有趣的新特性。在本教程中,您将学习七个最受关注的ES2020特性:BigInt动态导入、matchAll()可选链式调用和空值合并运算符。globalThisPromise.allSettled()
BigInt
ES2020 的第一个特性,名为 `int` 的新数据类型BigInt,乍一看似乎微不足道。对许多 JavaScript 开发者来说,这或许确实如此。然而,对于需要处理大数的开发者而言,它却意义重大。在 JavaScript 中,可处理的数字大小是有限制的,这个限制是 2^53 - 1。
在引入这种类型之前,由于数据类型无法处理如此大的数字,BigInt因此无法突破这个限制。有了这种类型,您就可以创建、存储和处理这些大数字,包括超过安全整数限制的偶数。创建这种类型有两种方法。NumberBigIntBigInt
第一种方法是使用BigInt()构造函数。该构造函数接受一个要转换成的数字BigInt作为参数,并返回转换后的数字BigInt。第二种方法是在整数末尾添加“n”。在这两种情况下,JavaScript 都会将“n”添加到要转换成的数字中BigInt。
这个“n”告诉 JavaScript,当前数字是一个整数BigInt,不应该被当作整数处理Number。这也意味着一件事:记住,整数BigInt不是Number数据类型,而是BigInt数据类型。与整数进行严格比较Number总是会失败。
// Create the largest integer
let myMaxSafeInt = Number.MAX_SAFE_INTEGER
// Log the value of "myMaxSafeInt":
console.log(myMaxSafeInt)
// Output:
// 9007199254740991
// Check the type of "myMaxSafeInt":
console.log(typeof myMaxSafeInt)
// Output:
// 'number'
// Create BigInt with BigInt() function
let myBigInt = BigInt(myMaxSafeInt)
// Log the value of "myBigInt":
console.log(myBigInt)
// Output:
// 9007199254740991n
// Check the type of "myBigInt":
console.log(typeof myBigInt)
// Output:
// 'bigint'
// Compare "myMaxSafeInt" and "myBigInt":
console.log(myMaxSafeInt === myBigInt)
// Output:
// false
// Try to increase the integer:
++myMaxSafeInt
// Output:
// 9007199254740992
++myMaxSafeInt
// Output:
// 9007199254740992
++myMaxSafeInt
// Output:
// 9007199254740992
// Try to increase the BIgInt:
++myBigInt
// Output:
// 9007199254741007n
++myBigInt
// Output:
// 9007199254741008n
++myBigInt
// Output:
// 9007199254741009n
String.prototype.matchAll()
这matchAll()是 ES2020 特性列表中另一个较小的功能,但它非常实用。这个方法可以帮助你在字符串中查找所有与正则表达式匹配的项。该方法返回一个迭代器。有了这个迭代器,你至少可以做两件事。
首先,您可以使用for...of循环遍历迭代器并获取每个匹配项。第二种方法是将迭代器转换为数组。每个匹配项及其对应的数据将成为数组中的一个单独元素。
// Create some string:
const myStr = 'Why is the answer 42, what was the question that led to 42?'
// Create some regex patter:
const regexp = /\d/g
// Find all matches:
const matches = myStr.matchAll(regexp)
// Get all matches using Array.from():
Array.from(matches, (matchEl) => console.log(matchEl))
// Output:
// [
// '4',
// index: 18,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '2',
// index: 19,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '4',
// index: 56,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '2',
// index: 57,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// Get all matches using for...of loop:
for (const match of matches) {
console.log(match)
}
// Output:
// [
// '4',
// index: 18,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '2',
// index: 19,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '4',
// index: 56,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
// [
// '2',
// index: 57,
// input: 'Why is the answer 42, what was the question that led to 42?',
// groups: undefined
// ]
全球这
使用不同环境的 JavaScript 开发人员必须记住,存在不同的全局对象。例如,window浏览器中有 `javascript` 对象,而 Node.js 中有 ` globaljavascript` 对象,Web Worker 中则有 `javascript` 对象self。ES2020 的一个旨在简化此过程的特性是 `javascript` globalThis。
这globalThis本质上是一种标准化全局对象的方法。您不再需要自行检测全局对象并修改代码。相反,您可以使用它globalThis。它将始终引用您当前工作环境中的全局对象。
// In Node.js:
console.log(globalThis === global)
// Output:
// true
// In browser:
console.log(globalThis === window)
// Output:
// true
动态导入
您需要处理的一个问题是各种导入和日益增多的脚本。以前,无论条件如何,导入任何模块都必须执行。有时,根据应用程序的动态需求,您甚至需要导入一个实际上并未使用的模块。
ES2020 的一个非常流行的特性是动态导入。动态导入的作用很简单:它允许你在需要时导入模块。例如,假设你知道某个模块只有在特定条件下才需要使用,那么你可以使用if...else 语句来判断是否满足该条件。
如果满足条件,你可以指示 JavaScript 导入模块以便使用它。这意味着在语句中插入动态导入语句。只有当条件满足时,模块才会加载。否则,如果条件不满足,则不会加载任何模块,也不会导入任何内容。这样可以减少代码量、降低内存占用等等。
当你想使用动态导入导入某个模块时,你import像往常一样使用 `import` 关键字。但是,对于动态导入,你需要将其作为函数调用。你要导入的模块就是传递给该函数的参数。这个导入函数会返回一个Promise 对象。
当 Promise 被处理后,你可以使用`then() ` 处理函数来操作导入的模块。另一种方法是使用`await`关键字,并将返回值(即模块)赋值给一个变量。然后,你可以使用该变量来操作导入的模块。
// Dynamic import with promises:
// If some condition is true:
if (someCondition) {
// Import the module as a promise
// and use then() to process the returned value:
import('./myModule.js')
.then((module) => {
// Do something with the module
module.someMethod()
})
.catch(err => {
console.log(err)
})
}
// Dynamic import with async/await:
(async() => {
// If some condition is true:
if (someCondition) {
// Import the module and assign it to a variable:
const myModule = await import('./myModule.js')
// Do something with the module
myModule.someMethod()
}
})()
Promise.allSettled()
有时,你有很多 Promise,并不关心哪些 Promise 被解决,哪些被拒绝。你只想知道这些 Promise 何时全部解决。这时,你就可以使用这个新allSettled()方法了。该方法接受一个数组形式的 Promise 对象。
只有当数组中的所有 Promise 都已解决时,此方法才会执行。部分或全部 Promise 是否已解决或被拒绝并不重要,重要的是它们都必须得到解决。当所有 Promise 都得到解决时,该allSettled()方法将返回一个新的 Promise。
此承诺的值将是一个数组,其中包含每个承诺的状态。它还将包含每个已完成承诺的值以及每个已拒绝承诺的原因。
// Create few promises:
const prom1 = new Promise((resolve, reject) => {
resolve('Promise 1 has been resolved.')
})
const prom2 = new Promise((resolve, reject) => {
reject('Promise 2 has been rejected.')
})
const prom3 = new Promise((resolve, reject) => {
resolve('Promise 3 has been resolved.')
})
// Use allSettled() to wait until
// all promises are settled:
Promise.allSettled([prom1, prom2, prom3])
.then(res => console.log(res))
.catch(err => console.log(err))
// Output:
// [
// { status: 'fulfilled', value: 'Promise 1 has been resolved.' },
// { status: 'rejected', reason: 'Promise 2 has been rejected.' },
// { status: 'fulfilled', value: 'Promise 3 has been resolved.' }
// ]
可选链式连接
作为一名 JavaScript 开发者,你可能经常需要处理对象及其属性和值。一个好习惯是在尝试访问某个属性之前先检查它是否存在。如果对象结构比较浅,这样做没问题。但如果对象结构比较深,就会很快变得很麻烦。
当您需要在多个层级检查属性时,很快就会遇到条件语句过长而无法在一行代码中完整显示的情况。ES2020 的可选链功能或许可以解决这个问题。这项功能备受关注,这并不奇怪,因为它确实非常实用。
可选链式调用允许你访问深层嵌套的对象属性,而无需担心属性是否存在。如果属性存在,你将获得它的值;如果属性不存在,你将获得空值undefined,而不是报错。可选链式调用的另一个优点是它也适用于函数调用和数组。
// Create an object:
const myObj = {
prop1: 'Some prop.',
prop2: {
prop3: 'Yet another prop.',
prop4: {
prop5: 'How deep can this get?',
myFunc: function() {
return 'Some deeply nested function.'
}
}
}
}
// Log the value of prop5 no.1: without optional chaining
// Note: use conditionals to check if properties in the chain exist.
console.log(myObj.prop2 && myObj.prop2.prop4 && myObj.prop2.prop4.prop5)
// Output:
// 'How deep can this get?'
// Log the value of prop3 no.2: with optional chaining:
// Note: no need to use conditionals.
console.log(myObj.prop2?.prop4?.prop5)
// Output:
// 'How deep can this get?'
// Log non-existent value no.1: without optional chaining
console.log(myObj.prop5 && myObj.prop5.prop6 && myObj.prop5.prop6.prop7)
// Output:
// undefined
// Log non-existent value no.2: with optional chaining
// Note: no need to use conditionals.
console.log(myObj.prop5?.prop6?.prop7)
// Output:
// undefined
空合并算子
空值合并运算符(nullish coalescing operator)也是 ES2020 中备受关注的特性之一。众所周知,使用可选链可以访问嵌套属性而无需担心它们是否存在。如果属性不存在,则会返回 undefined。空值合并运算符通常与可选链一起使用。
空值合并运算符的作用是帮助你检查“空”值并采取相应的操作。那么“空”值有什么意义呢?在 JavaScript 中,值分为两种类型:假值和真值。假值是空字符串,例如 0、`null` undefined、null`null` false、NaN`null` 等等。
问题在于,这使得检查某个值是否仅为 `true`null或 `false`变得更加困难undefined。`true`null和undefined`false` 都为假值,在布尔上下文中会被转换为 `true` false。如果使用空字符串或 0,也会发生同样的情况,它们最终也会被放入false布尔上下文中。
你可以通过专门检查 `null`undefined和 `null`来避免这种情况null。但是,这需要编写更多代码。另一种方法是使用空值合并运算符。如果空值合并运算符左侧的表达式求值为 `null`undefined或 `null` null,它将返回右侧的结果;否则,返回左侧的结果。
还有一点。语法方面,空值合并运算符的语法非常简单,它由两个问号组成??。如果您想了解更多关于空值合并运算符的信息,请参阅这篇教程。
// Create an object:
const friend = {
firstName: 'Joe',
lastName: undefined, // Falsy value.
age: 0, // falsy value.
jobTitle: '', // Falsy value.
hobbies: null // Falsy value.
}
// Example 1: Without nullish coalescing operator
// Note: defaults will be returned for every falsy value.
// Log the value of firstName (value is 'Joe' - truthy)
console.log(friend.firstName || 'First name is unknown.')
// Output:
// 'Joe'
// Log the value of lastName (value is undefined - falsy)
console.log(friend.lastName || 'Last name is unknown.')
// Output:
// 'Last name is unknown.'
// Log the value of age (value is 0 - falsy)
console.log(friend.age || 'Age is unknown.')
// Output:
// 'Age is unknown.'
// Log the value of jobTitle (value is '' - falsy)
console.log(friend.jobTitle || 'Job title is unknown.')
// Output:
// 'Job title is unknown.'
// Log the value of hobbies (value is null - falsy)
console.log(friend.hobbies || 'Hobbies are unknown.')
// Output:
// 'Hobbies are unknown.'
// Log the value of non-existing property pets (falsy)
console.log(friend.pets || 'Pets are unknown.')
// Output:
// 'Pets are unknown.'
// Example 2: With nullish coalescing operator
// Note: defaults will be returned only for null and undefined.
// Log the value of firstName (value is 'Joe' - truthy)
console.log(friend.firstName ?? 'First name is unknown.')
// Output:
// 'Joe'
// Log the value of lastName (value is undefined - falsy)
console.log(friend.lastName ?? 'Last name is unknown.')
// Output:
// 'Last name is unknown.'
// Log the value of age (value is 0 - falsy)
console.log(friend.age ?? 'Age is unknown.')
// Output:
// 0
// Log the value of jobTitle (value is '' - falsy)
console.log(friend.jobTitle ?? 'Job title is unknown.')
// Output:
// ''
// Log the value of hobbies (value is null - falsy)
console.log(friend.hobbies ?? 'Hobbies are unknown.')
// Output:
// 'Hobbies are unknown.'
// Log the value of non-existing property pets (falsy)
console.log(friend.pets ?? 'Pets are unknown.')
// Output:
// 'Pets are unknown.'
结论:你应该尝试的 7 个 JavaScript ES2020 特性
ES2020 规范引入了许多特性。其中一些特性非常有趣,而另一些则相对逊色。今天你了解到的这七个 ES2020 特性就属于值得关注的范畴。我希望这篇教程能帮助你理解这些特性的工作原理以及如何使用它们。
文章来源:https://dev.to/alexdevero/7-javascript-es2020-features-you-should-try-4p9d