即将推出的值得关注的 JavaScript ES2021(ES12)功能
ES2021(ES12)将于 2021 年中期发布。在本教程中,您将了解此规范中最有趣的五个特性:String.prototype.replaceAll()
、数字分隔符、逻辑赋值运算符Promise.any()
、WeakRef
和终结器。
关于功能的简要说明
您将在本文中阅读到的所有五个功能目前都处于第 4 阶段。这意味着它们已经完成,并准备好由 JavaScript 引擎实现。这也意味着您不必担心会浪费时间学习一些永远不会实现的东西。您不会的。
所有这些功能即将发布。如果您感兴趣,可以在Ecma TC39 官方 GitHub 仓库中了解更多其他提案。该仓库跟踪所有提案以及每个提案当前所处的阶段。现在,让我们来看看 ES2021 规范将带来哪些有趣的功能。
String.prototype.replaceAll()
让我们从 JavaScript ES2021 中一个较小的功能开始,但它仍然是语言的一个不错的补充,replaceAll()
那就是方法。目前,当你想替换 [string] 中某个模式的多次出现时,可以使用replace() 方法。问题是什么?如果你使用字符串,这将只允许你替换该模式的第一次出现。
这并不意味着replace()
如果你想替换所有出现的模式,该方法就没用。它也能完成这项工作。但是,你必须使用正则表达式。如果你觉得可以,那就没问题。对于许多开发人员来说,正则表达式并不是他们的首选。远非如此。
如果您是这些开发人员之一,您一定会喜欢这个新replaceAll()
方法。此方法的工作方式与方法类似replace()
。不同之处在于,它replaceAll()
允许您替换所有出现的模式,而无需使用正则表达式。
该replaceAll()
方法也接受正则表达式。所以,如果你喜欢正则表达式,你也可以使用它。你也可以使用函数来替代它。如果这样做,这个函数会在字符串中的每个匹配项执行。你可以在官方仓库中阅读这个提案。
// Declare a string:
let str = 'There are those who like cats, there those who like watching cats and there are those who have cats.'
// Replace all occurrences of "cats" with dogs:
str = str.replaceAll('cats', 'dogs')
// Log the new value of "str":
console.log(str)
// Output:
// 'There are those who like dogs, there those who like watching dogs and there are those who have dogs.'
// A simple alternative with replace():
str = str.replace(/cats/g, 'dogs')
// Log the new value of "str":
console.log(str)
// Output:
// 'There are those who like dogs, there those who like watching dogs and there are those have dogs.'
数字分隔符
这是 JavaScript ES2021 中另一个非常小的功能,但它至少能让你的工作效率提升一些。尤其是在处理大数字时。数字分隔符提供了一种简单易用的方法,让大数字更易读、更易于操作。它的语法也同样简单,就是一个下划线 ( _
)。
// Number without numeric separators:
const num = 3685134689
// Number with numeric separators:
const num = 3_685_134_689
请记住,数字分隔符只是视觉辅助。使用它们不会对数值本身产生任何影响。例如,如果您尝试使用数字分隔符记录数字,您将获得“原始”和“未编辑”的版本。
// Use numeric separators with a number:
const num = 3_685_134_689
// Log the value of "num":
console.log(num)
// Output:
// 3685134689
逻辑赋值运算符
JavaScript 允许在布尔上下文中使用逻辑运算符。例如,在if...else 语句和三元运算符中,用于测试真值。ES2021 和逻辑赋值运算符将改变这一规则。这些运算符允许你将逻辑运算符与赋值表达式 ( =
) 结合使用。
您可以使用一些已经存在一段时间的赋值运算符+=
。例如,加法赋值 ( )、减法赋值 ( -=
)、乘法赋值 ( *=
) 等等。得益于 ES2021,您还可以使用逻辑运算符 ( &&
,||
和??
(空值合并))。
//
// AND AND equals (&&=)
x &&= y
// Is equivalent to:
x = x && d
// Or:
if (x) {
x = y
}
// Example 1:
let x = 3 // Truthy value.
let y = 0 // Falsy value.
x &&= y
// Log the value of "x":
console.log(x)
// Output:
// 0
// Example 2:
let x = 0 // Falsy value.
let y = 9 // Truthy value.
x &&= y
// Log the value of "x":
console.log(x)
// Output:
// 0
// Example 3:
let x = 3 // Truthy value.
let y = 15 // Truthy value.
x &&= y
// Log the value of "x":
console.log(x)
// Output:
// 15
//
// OR OR equals (||=):
x ||= y
// Is equivalent to:
x = x || y
// Or:
if (!x) {
x = y
}
// Example 1:
let x = 3 // Truthy value.
let y = 0 // Falsy value.
x ||= y
// Log the value of "x":
console.log(x)
// Output:
// 3
// Example 2:
let x = 0 // Falsy value.
let y = 9 // Truthy value.
x ||= y
// Log the value of "x":
console.log(x)
// Output:
// 9
// Example 3:
let x = 3 // Truthy value.
let y = 15 // Truthy value.
x ||= y
// Log the value of "x":
console.log(x)
// Output:
// 3
//
// Nullish coalescing (??):
x ??= y
// Is equivalent to:
x = x ?? y
// Or:
if (x == null || x == undefined) {
x = y
}
// Example 1:
let x = null // Null value.
let y = 'Hello' // Non-null value.
x ??= y
// Log the value of "x":
console.log(x)
// Output:
// 'Hello'
// Example 2:
let x = 'Jay' // Non-null value.
let y = 'Hello' // Non-null value.
x ??= y
// Log the value of "x":
console.log(x)
// Output:
// 'Jay'
// Example 3:
let x = 'Jay' // Non-null value.
let y = null // Null value.
x ??= y
// Log the value of "x":
console.log(x)
// Output:
// 'Jay'
// Example 4:
let x = undefined // Non-null value.
let y = 'Jock' // Null value.
x ??= y
// Log the value of "x":
console.log(x)
// Output:
// 'Jock'
让我们看一下上面的例子。首先, 。只有当为真时,x &&= y
才会赋值y
给。否则,它会赋值给。其次, 。只有当为假值时,才会赋值给。如果为真且为假,则赋值不会发生。x
x
y
x ||= y
y
x
x
x
y
x
如果和都为假,也会发生同样的情况y
。最后一个, 。只有当是或 时,x ??= y
才会赋值y
给。如果既不是也不是 ,则赋值不会发生。如果是或 ,情况也一样。x
x
null
undefined
x
null
undefined
y
null
undefined
Promise.any()
说到JavaScript 的 Promise,过去一两年可谓是相当火爆。ES6 引入了Promise.race()
和Promise.all()
方法。之后,ES2020 又带来了Promise.allSettled()
。ES2021 带来了另一种方法,可以让 Promise 的使用更加便捷,那Promise.any()
就是 方法。
该Promise.any()
方法接受多个 Promise,并在其中任何一个 Promise 实现时返回一个 Promise。第一个实现的 Promise 是 返回的 Promise Promise.any()
。如果您提供的所有 Promise 均被拒绝,Promise.any()
则将返回AggregateError
。其中包含拒绝的原因。
// Example 1: All resolve:
// Create promises:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1 is resolved.')
}, Math.floor(Math.random() * 1000))
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise2 is resolved.')
}, Math.floor(Math.random() * 1000))
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise3 is resolved.')
}, Math.floor(Math.random() * 1000))
})
;(async function() {
// Await the result of Promise.any():
const result = await Promise.any([promise1, promise2, promise3])
// Log the value returned by Promise.any():
console.log(result)
// Output:
// 'promise1 is resolved.', 'promise2 is resolved.' or 'promise3 is resolved.'
})()
// Example 2: Some resolve:
// Create promises:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1 is resolved.')
}, Math.floor(Math.random() * 1000))
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise2 was rejected.')
}, Math.floor(Math.random() * 1000))
})
;(async function() {
// Await the result of Promise.any():
const result = await Promise.any([promise1, promise2])
// Log the value returned by Promise.any():
console.log(result)
// Output:
// 'promise1 is resolved.'
})()
// Example 3: None resolves:
// Create promises:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise1 was rejected.')
}, Math.floor(Math.random() * 1000))
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise2 was rejected.')
}, Math.floor(Math.random() * 1000))
})
;(async function() {
// Use try...catch to catch the AggregateError:
try {
// Await the result of Promise.any():
const result = await Promise.any([promise1, promise2])
}
catch (err) {
console.log(err.errors)
// Output:
// [ 'promise1 was rejected.', 'promise2 was rejected.' ]
}
})()
弱引用
ES2021 的最后一个显著特性是WeakRefs
。在 JavaScript 中,当你创建对某个对象的引用时,它会阻止该对象被Garage Collection回收。这意味着 JavaScript 无法移除该对象并释放其内存。只要存在对它的引用,对象就可能永远存在。
ES2021 引入了新的 class WeakRefs
。这将允许开发者创建对对象的弱引用。借助它,开发者可以跟踪现有对象,而不会阻止它们被垃圾回收。这对于缓存和对象映射非常有用。
当你想要创建新对象时WeakRef
,必须使用new
关键字 new 。你需要将某个对象作为参数传入括号中。当你想要读取引用(被引用的对象)时,可以通过调用deref()
弱引用来实现。我们来看一个非常简单的例子。
const myWeakRef = new WeakRef({
name: 'Cache',
size: 'unlimited'
})
// Log the value of "myWeakRef":
console.log(myWeakRef.deref())
// Output:
// { name: 'Cache', size: 'unlimited' }
// Log the value of "name" property:
console.log(myWeakRef.deref().name)
// Output:
// 'Cache'
// Log the value of "size" property:
console.log(myWeakRef.deref().size)
// Output:
// 'unlimited'
Finalizers 和 FinalizationRegistry
与 紧密相关的是WeakRef
,ES2021 还有另一个称为 终结器 (或 )的功能FinalizationRegistry
。此功能允许您注册将在对象被垃圾回收时调用的回调函数。
// Create new FinalizationRegistry:
const reg = new FinalizationRegistry((val) => {
// Print the value of "val" when invoked:
console.log(val)
})
;(() => {
// Create new object:
const obj = {}
// Register finalizer for the "obj" obj:
// 1st argument: object to register finalizer for.
// 2nd argument: value for callback function defined above.
reg.register(obj, 'obj has been garbage-collected.')
})()
// Output when "obj" is garbage-collected:
// 'obj has been garbage-collected.'
关于 finalizer 和 finalizer 有一点很重要WeakRef
。该特性的提案本身建议不要使用它们。原因之一是它们可能不可预测。另一个原因是它们实际上并没有帮助垃圾收集器完成其工作。它们实际上会使垃圾收集器的工作更加困难。您可以在提案中阅读更多关于原因的内容。
结论:值得关注的 JavaScript ES2021(ES12)新功能
与之前的 JavaScript 规范(例如 ES6 和 ES2020)相比,ES2021(ES12)可能显得微不足道。然而,它有一些值得关注的有趣特性。希望本教程能帮助您了解这五个实用特性,让您的工作更轻松。
鏂囩珷鏉ユ簮锛�https://dev.to/alexdevero/upcoming-interesting-javascript-es2021-es12-features-to-look-for-1oe8