首頁  >  文章  >  web前端  >  搶先體驗JavaScript ES12新特性

搶先體驗JavaScript ES12新特性

coldplay.xixi
coldplay.xixi轉載
2020-11-03 17:20:432659瀏覽

JavaScript欄位介紹體驗ES12新功能。

搶先體驗JavaScript ES12新特性

而每年,JavaScript都會更新新增的功能新標準,在今年ES2020發布了,而ES2020(ES12)也預計在明年即2021年年中發布。每年的新特性都會經歷四個階段,而第四階段也就是最後一個階段,本文即將介紹的即提案4中的相關新特性,也是意味著這些新特性將很大程度的出現在下一個版本中

特性搶先知:

  • String.prototype.replaceAll 新增replaceAll
  • Promise.any
  • WeakRefs
  • 邏輯運算子和賦值表達式
  • 數字分隔符號

replaceAll

看到replaceAll這個詞,比較很容易聯想到replace。在JavaScript中,replace方法只能是替換字串中匹配到的第一個實例字符,而不能進行全域多項匹配替換,唯一的辦法是透過正規表示式進行相關規則匹配替換

#而replaceAll則是傳回一個全新的字串,所有符合符合規則的字元都會被替換掉,替換規則可以是字串或正規表示式。

let string = 'I like 前端,I like 前端公虾米'//使用replacelet replaceStr = string.replace('like','love')console.log(replaceStr)  // 'I love 前端,I like 前端公虾米'//replace使用正则匹配所有console.log(string.replace(/like/g,'love')) // 'I love 前端,I love 前端公虾米'//使用replaceAlllet replaceAllStr = string.replaceAll('like','love')console.log(replaceAllStr) // 'I love 前端,I love 前端公虾米'复制代码

要注意的是,replaceAll在使用正規表示式的時候,如果非全域匹配(/g),則replaceAll()會拋出一個異常

let string = 'I like 前端,I like 前端公虾米'console.log(string.replaceAll(/like/,'love')) //TypeError复制代码

Promise.any

當Promise清單中的任一promise成功resolve則傳回第一個resolve的結果狀態 如果所有的promise均reject,則拋出異常表示所有請求失敗

Promise.any([  new Promise((resolve, reject) => setTimeout(reject, 500, '哎呀,我被拒绝了')),  new Promise((resolve, reject) => setTimeout(resolve, 1000, '哎呀,她接受我了')),  new Promise((resolve, reject) => setTimeout(resolve, 2000, '哎呀,她也接受我了')),
])
.then(value => console.log(`输出结果: ${value}`))
.catch (err => console.log(err))//输出//输出结果:哎呀,她接受我了复制代码

再來看下另一種情況

Promise.any([  Promise.reject('Error 1'),  Promise.reject('Error 2'),  Promise.reject('Error 3')
])
.then(value => console.log(`请求结果: ${value}`))
.catch (err => console.log(err))//输出AggregateError: All promises were rejected复制代码

Promise.anyPromise.race十分容易混淆,務必注意區分,Promise.race 一旦某個promise觸發了resolve或reject,就直接返回了該狀態結果,並不在乎其成功或失敗

WeakRefs

使用WeakRefs的Class類別建立對物件的弱引用(對物件的弱引用是指當該物件應該被GC回收時不會阻止GC的回收行為)

當我們透過(const、let、var)建立變數時,垃圾收集器GC將永遠不會從記憶體中刪除該變量,只要它的引用仍然存在可訪問。 WeakRef物件包含對物件的弱引用。對物件的弱引用是不會阻止垃圾收集器GC恢復該物件的引用,則GC可以在任何時候刪除它。

WeakRefs在許多情況下都很有用,例如使用Map物件來實現具有許多需要大量記憶體的鍵值緩存,在這種情況下最方便的就是盡快釋放鍵值對佔用的記憶體。

目前,可以透過WeakMap()或WeakSet()來使用WeakRefs

舉個栗子

我想要追蹤特定的物件呼叫某一特定方法的次數,超過1000條則做對應提示

let map = new Map()function doSomething(obj){
	...
}function useObject(obj){
	doSomething(obj)  
  let called = map.get(obj) || 0
  called ++ 
  
  if(called>1000){     console.log('当前调用次数已经超过1000次了,over')
  }
  
  map.set(obj, called)
}复制代码

如上雖然可以實現我們的功能,但是會發生記憶體溢出,因為傳遞給doSomething函數的每個物件都永久保存在map中,並且不會被GC回收,因此我們可以使用WeakMap

let wmap = new WeakMap()function doSomething(obj){
	...
}function useObject(obj){
	doSomething(obj)  
  let called = wmap.get(obj) || 0
  
  called ++  
  if(called>1000){     console.log('当前调用次数已经超过1000次了,over')
  }
  
  wmap.set(obj, called)
}复制代码

因為是弱引用,所以WeakMap、WeakSet的鍵值對是不可枚舉

WeakSet和WeakMap相似,但是每個物件在WeakSet中的每個物件只可能出現一次,WeakSet中所有物件都是唯一的

let ws = new WeakSet()let foo = {}let bar = {}

ws.add(foo)
ws.add(bar)

ws.has(foo) //truews.has(bar) //truews.delete(foo) //删除foo对象ws.has(foo) //false 已删除ws.has(bar) //仍存在复制代码

WeakSetSet比較有以下兩個差異

  • WeakSet只能是物件集合,而不能是任何類型的任意值
  • WeakSet弱引用,集合中物件引用為弱引用,如果沒有其他對WeakSet物件的引用,則會被GC回收

最後,WeakRef實例有一個方法deref,返回引用的原始對象,如果原始對像被回收,則返回undefined

const cache = new Map();const setValue =  (key, obj) => {
  cache.set(key, new WeakRef(obj));
};const getValue = (key) => {  const ref = cache.get(key);  if (ref) {    return ref.deref();
  }
};const fibonacciCached = (number) => {  const cached = getValue(number);  if (cached) return cached;  const sum = calculateFibonacci(number);
  setValue(number, sum);  return sum;
};复制代码

對於緩存遠端資料來說,這可能不是一個好主意,因為遠端資料可能會不可預測地從記憶體中刪除。在這種情況下,最好使用LRU之類的快取。

邏輯運算子和賦值表達式

邏輯運算子和賦值表達式,新特性結合了邏輯運算子(&&,||,??)和賦值表達式而JavaScript已存在的 複合賦值運算子有:

  • 運算子: =   -=   *=   /=   %=   **=
  • #位元運算子:&=   ^=   | =
  • 位元運算子:<<=   >>=   >>>=

現有的的運算符,其運作方式都可以如此來理解

表達式:a op= b

等同於:a = a op b

邏輯運算子和其他的複合賦值運算子工作方式不同

表達式:a op= b

等同於:a = a op (a = b)

a ||= b//等价于a = a || (a = b)

a &&= b//等价于a = a && (a = b)

a ??= b//等价于a = a ?? (a = b)复制代码

为什么不再是跟以前的运算公式a = a op b一样呢,而是采用a = a op (a = b)。因为后者当且仅当a的值为false的时候才计算赋值,只有在必要的时候才执行分配,而前者的表达式总是执行赋值操作

??=可用来补充/初始化缺失的属性

const pages = [
  {  	title:'主会场',    path:'/'
  },
  {    path:'/other'
  },
  ...
]  
for (const page of pages){
	page.title ??= '默认标题'}console.table(pages)//(index)  title       		path//0        "主会场"   	  "/"//1        "默认标题"  	 "/other"复制代码

小结:

  • &&=:当LHS值存在时,将RHS变量赋值给LHS
  • ||=:当LHS值不存在时,将RHS变量赋值给LHS
  • ??= :当LHS值为null或者undefined时,将RHS变量赋值给LHS

数字分隔符

数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性

const money = 1_000_000_000//等价于const money = 1000000000const totalFee = 1000.12_34//等价于const totalFee = 1000.1234复制代码

该新特性同样支持在八进制数中使用

const number = 0o123_456//等价于const number = 0o123456复制代码

该新特性方便读取数据,可以让我们打工人更容易辨认"资产" 不过话说回来,小编的资产好像不配使用该特性...敲重点!!!

本次所有新特性均介绍的第4阶段,意味着将出现在下一个版本中的,没有介绍阶段3的,因为不确定是否一定会出现在下个版本中。本文介绍的新特性均可直接在最新版的谷歌浏览器中愉快体验。

相关免费学习推荐:javascript(视频)

以上是搶先體驗JavaScript ES12新特性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除