即将发布的ES2021中有哪些有趣的功能

本文转载自微信公众号“前端先锋”(jingchengyideng)。

简述

ES2021(ES12)将于 2021 年中发布。在本文中,你将将会了解五个最有趣的功能:String.prototype.replaceAll(),数字分隔符,逻辑赋值运算符,Promise.any(),WeakRef 和Finalizers。

本文所描述的五个功能目前都处于第 4 阶段。这意味着它们已经完成,并将要在 JavaScript 引擎中实现了。这意味着你不会浪费时间去学习一些可能永远也不会出现的东西。

这些功能不久将会发布。如果有兴趣,可以到官方 Ecma TC39 GitHub (https://github.com/tc39/proposals) 去了解有关其他提案的更多信息。这个 Github 库跟踪了所有提案以及其当前所处的阶段。

String.prototype.replaceAll()

先从一个小功能 replaceAll() 开始,这是对 JavaScript 语言的一个补充。当你要替换字符串中多次出现的匹配模式时,目前可以用 replace() 方法,但问题是它只能替换第一次出现的那个。

这并不意味着 replace() 不能替换所有出现的匹配模式,只不过你必须用正则表达式才行。如果你可以接受那就没事儿了。不过对于很多 js 程序员来说,正则表达式并不是他们的菜(实际上是懒得学!)。

如果你就是这样的 js 程序员,肯定喜欢新的 replaceAll() 方法。它的工作方式与 replace() 类似,区别在于 replaceAll() 可以不用正则表达式就能替换所有出现的模式。

replaceAll() 也能接受正则表达式,你完全可以用它代替 replace() 。

 
 
 
 
  1. // 声明一个字符串
  2. let str = 'There are those who like cats, there those who like watching cats and there are those who have cats.'
  3. // 用 dogs 替换所有的“cats”:
  4. strstr = str.replaceAll('cats', 'dogs')
  5. console.log(str)
  6. // Output:
  7. // 'There are those who like dogs, there those who like watching dogs and there are those who have dogs.'
  8. // 用 replace() 的写法:
  9. strstr = str.replace(/cats/g, 'dogs')
  10. console.log(str)
  11. // Output:
  12. // 'There are those who like dogs, there those who like watching dogs and there are those have dogs.'

数字分隔符

这是 JavaScript ES2021的一个非常小的功能,可以让你在处理大量数字时更好过一点。数字分隔符提供了一种能使大数字更易于阅读和使用的简单方法。语法也很简单:一个下划线 _。

 
 
 
 
  1. // 不带数字分隔符的 Number 
  2. const num = 3685134689
  3. // 带数字分隔符的 Number 
  4. const num = 3_685_134_689

不过数字分隔符只是在视觉上提供一些帮助。在使用时不会对数值本身产生任何影响。

 
 
 
 
  1. // 带数字分隔符的 Number 
  2. const num = 3_685_134_689
  3. // 输出:
  4. console.log(num)
  5. // Output:
  6. // 3685134689

逻辑赋值运算符

JavaScript 允许在布尔上下文中使用逻辑运算符。例如在 if ... else语句和三目运算符中检测是 true 还是 false。ES2021 的逻辑赋值运算符将逻辑运算符与赋值表达式(=)组合在了一起。

在 JavaScript 中已经有了一些赋值运算符,例如:加法赋值(+=),减法赋值(-=),乘法赋值(*=)等。在 ES2021 中又增加了对逻辑运算符 &&,|| 和 ??([空值合并)的支持。

 
 
 
 
  1. //////////////////
  2. // 逻辑与赋值运算符 (&&=)
  3. //////////////////
  4. x &&= y
  5. // 以上代码相当于:
  6. xx = x && d
  7. // 或者:
  8. if (x) {
  9.   x = y
  10. }
  11. // 例1:
  12. let x = 3 
  13. let y = 0 
  14. x &&= y
  15. console.log(x)
  16. // Output:
  17. // 0
  18. // 例 2:
  19. let x = 0 
  20. let y = 9 
  21. x &&= y
  22. console.log(x)
  23. // Output:
  24. // 0
  25. // 例 3:
  26. let x = 3 // Truthy value.
  27. let y = 15 // Truthy value.
  28. x &&= y
  29. console.log(x)
  30. // Output:
  31. // 15
  32. //////////////////
  33. // 逻辑或赋值运算符 (||=):
  34. x ||= y
  35. // 相当于:
  36. xx = x || y
  37. // 或者:
  38. if (!x) {
  39.   x = y
  40. }
  41. // 例 1:
  42. let x = 3
  43. let y = 0
  44. x ||= y
  45. console.log(x)
  46. // Output:
  47. // 3
  48. // 例 2:
  49. let x = 0 
  50. let y = 9 
  51. x ||= y
  52. console.log(x)
  53. // Output:
  54. // 9
  55. // 例 3:
  56. let x = 3 
  57. let y = 15
  58. x ||= y
  59. console.log(x)
  60. // Output:
  61. // 3
  62. /////////////////////////
  63. // 空值合并赋值运算符 (??=):
  64. /////////////////////////
  65. x ??= y
  66. // 相当于:
  67. xx = x ?? y
  68. // 或者:
  69. if (x == null || x == undefined) {
  70.     x = y
  71. }
  72. // 例 1:
  73. let x = null 
  74. let y = 'Hello' 
  75. x ??= y
  76. console.log(x)
  77. // Output:
  78. // 'Hello'
  79. // 例 2:
  80. let x = 'Jay' 
  81. let y = 'Hello' 
  82. x ??= y
  83. console.log(x)
  84. // Output:
  85. // 'Jay'
  86. // 例 3:
  87. let x = 'Jay'
  88. let y = null 
  89. x ??= y
  90. console.log(x)
  91. // Output:
  92. // 'Jay'
  93. // 例 4:
  94. let x = undefined 
  95. let y = 'Jock' 
  96. x ??= y
  97. console.log(x)
  98. // Output:
  99. // 'Jock'

看一下上面的例子。首先是 x && = y。仅当 x 为真时,才将 y 赋值给 x。其次是 x || = y,仅当 x 为假时,才将 y 赋值给 x。如果 x 是真,而 y 是假,则不会进行赋值。

如果 x 和 y 都是假,也会发生同样的情况。最后是 x ?? = y。仅当 x 为 null 或 undefined 时,才将 y 分配给 x。如果 x 既不是 null 也不是 undefined 则不会进行赋值,如果 y 为 null 或 undefined 也一样。

Promise.any()

在 ES6 中引入了 Promise.race() 和 Promise.all() 方法,ES2020 加入了 Promise.allSettled()。ES2021 又增加了一个使 Promise 处理更加容易的方法:Promise.any() 。

Promise.any() 方法接受多个 promise,并在完成其中任何一个的情况下返回 promise。其返回的是 Promise.any() 完成的第一个 promise。如果所有 promise 均被拒绝,则 Promise.any() 将返回 AggregateError,其中包含拒绝的原因。

 
 
 
 
  1. // 例 1: 全部被完成:
  2. // 创建 promises:
  3. const promise1 = new Promise((resolve, reject) => {
  4.   setTimeout(() => {
  5.     resolve('promise1 is resolved.')
  6.   }, Math.floor(Math.random() * 1000))
  7. })
  8. const promise2 = new Promise((resolve, reject) => {
  9.   setTimeout(() => {
  10.     resolve('promise2 is resolved.')
  11.   }, Math.floor(Math.random() * 1000))
  12. })
  13. const promise3 = new Promise((resolve, reject) => {
  14.   setTimeout(() => {
  15.     resolve('promise3 is resolved.')
  16.   }, Math.floor(Math.random() * 1000))
  17. })
  18. ;(async function() {
  19.   // Await the result of Promise.any():
  20.   const result = await Promise.any([promise1, promise2, promise3])
  21.   console.log(result)
  22.   // Output:
  23.   // 'promise1 is resolved.', 'promise2 is resolved.' or 'promise3 is resolved.'
  24. })()
  25. // 例 2: 部分完成:
  26. const promise1 = new Promise((resolve, reject) => {
  27.   setTimeout(() => {
  28.     resolve('promise1 is resolved.')
  29.   }, Math.floor(Math.random() * 1000))
  30. })
  31. const promise2 = new Promise((resolve, reject) => {
  32.   setTimeout(() => {
  33.     reject('promise2 was rejected.')
  34.   }, Math.floor(Math.random() * 1000))
  35. })
  36. ;(async function() {
  37.   // Await the result of Promise.any():
  38.   const result = await Promise.any([promise1, promise2])
  39.   console.log(result)
  40.   // Output:
  41.   // 'promise1 is resolved.'
  42. })()
  43. // 例 3: 均被拒绝:
  44. const promise1 = new Promise((resolve, reject) => {
  45.   setTimeout(() => {
  46.     reject('promise1 was rejected.')
  47.   }, Math.floor(Math.random() * 1000))
  48. })
  49. const promise2 = new Promise((resolve, reject) => {
  50.   setTimeout(() => {
  51.     reject('promise2 was rejected.')
  52.   }, Math.floor(Math.random() * 1000))
  53. })
  54. ;(async function() {
  55.   // Use try...catch to catch the AggregateError:
  56.   try {
  57.     // Await the result of Promise.any():
  58.     const result = await Promise.any([promise1, promise2])
  59.   }
  60.   catch (err) {
  61.     console.log(err.errors)
  62.     // Output:
  63.     // [ 'promise1 was rejected.', 'promise2 was rejected.' ]
  64.   }
  65. })()

弱引用:WeakRef

最后一个抢眼的功能是 WeakRefs。在 JavaScript 中,当你创建了一个创建对象的引用时,这个引用可以防止对象被 gc 回收,也就是说 JavaScript 无法删除对象并释放其内存。只要对该对象的引用一直存在,就可以使这个对象永远存在。

ES2021 了新的类 WeakRefs。允许创建对象的弱引用。这样就能够在跟踪现有对象时不会阻止对其进行垃圾回收。对于缓存和对象映射非常有用。

必须用 new关键字创建新的 WeakRef ,并把某些对象作为参数放入括号中。当你想读取引用(被引用的对象)时,可以通过在弱引用上调用 deref() 来实现。下面是一个非常简单的例子。

 
 
 
 
  1. const myWeakRef = new WeakRef({
  2.   name: 'Cache',
  3.   size: 'unlimited'
  4. })
  5. console.log(myWeakRef.deref())
  6. // Output:
  7. // { name: 'Cache', size: 'unlimited' }
  8. console.log(myWeakRef.deref().name)
  9. // Output:
  10. // 'Cache'
  11. console.log(myWeakRef.deref().size)
  12. // Output:
  13. // 'unlimited'

Finalizers 和 FinalizationRegistry

与 WeakRef 紧密相连的还有另一个功能,名为 finalizers 或 FinalizationRegistry。这个功能允许你注册一个回调函数,这个回调函数将会在对象被 gc 回收时调用。

 
 
 
 
  1. // 创建 FinalizationRegistry:
  2. const reg = new FinalizationRegistry((val) => {
  3.   console.log(val)
  4. })
  5. ;(() => {
  6.   // 创建新对象:
  7.   const obj = {}
  8.   //为 “obj” 对象注册 finalizer:
  9.   //第一个参数:要为其注册 finalizer 的对象。
  10.   //第二个参数:上面定义的回调函数的值。
  11.   reg.register(obj, 'obj has been garbage-collected.')
  12. })()
  13. // 当 "obj" 被gc回收时输出:
  14. // 'obj has been garbage-collected.'

官方建议不要轻易使用 WeakRef 和 finalizer。其中一个原因是它们可能不可预测,另一个是它们并没有真正帮 gc 完成工作,实际上可能会gc的工作更加困难。你可以在它的提案(https://github.com/tc39/proposal-weakrefs#a-note-of-caution)中详细了解其原因。

总结

与以前的 JavaScript 规范(例如 ES6 和 ES2020)相比,看上去 ES2021的更新不多,但是这些有趣的功能值得我们关注。

当前标题:即将发布的ES2021中有哪些有趣的功能
网站地址:http://www.hantingmc.com/qtweb/news39/369539.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联