新特性總結如下:
1.String.prototype.replaceAll( )2.私有方法 Private Methods 與私有訪問者 Private Accessors3.Promise.any 與 AggregateError4.WeakRefs 弱引用5.邏輯運算子和賦值表示式String.prototype.replaceAll( )完全匹配替換字串
目前,JavaScript字串有replace方法可以用來做一個字串替換,
const str = "Backbencher sits at the Back"const newStr = str.replace("Back","Front")console.log(newStr)// "Frontbencher sits at the Back"
如果是要完全匹配我們只能用正則表示式,如下
const str = "Backbencher sits at the Back"const newStr = str.replace(/Back/g, "Front")console.log(newStr) // "Frontbencher sits at the Front"
使用replaceAll
const str = "Backbencher sits at the Back"const newStr = str.replaceAll("Back", "Front")console.log(newStr) // "Frontbencher sits at the Front"
私有方法 Private Methods
私有方法
私有方法只能在定義它的類內部訪問,專用方法名稱以開頭 #
class Person { // Private method #setType() { console.log("I am Private"); } // Public method show() { this.#setType(); }}const personObj = new Person()personObj.show() // "I am Private"personObj.setType() // TypeError: personObj.setType is not a function
由於setType()是私有方法,所以personObj.setType返回undefined,用undefined作函式會 引發TypeError。
私有訪問者 Private Accessors私有訪問者
可以透過 #在函式名稱前新增訪問器函式來使其私有
class Person { // Public accessor get name() { return "Backbencher" } set name(value) {} // Private accessor get #age() { return 42 } set #age(value) {}}
在上面的程式碼get和set關鍵字中,建立name了一個accessor屬性。使name看起來像一個函式,也可以像普通屬性一樣讀取它, 而age則是私有。
const obj = new Person()console.log(obj.name) // "Backbencher"console.log(obj.age) // undefined
Promise.any 與 AggregateError
當Promise列表中的任意一個promise成功resolve則返回第一個resolve的結果狀態, 如果所有的promise均reject,則丟擲異常表示所有請求失敗
Promise.any([ new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')), new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')), new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),]).then(value => console.log(`Result: ${value}`)) // Result: Second.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.any與Promise.race十分容易混淆,務必注意區分,Promise.race 一旦某個promise觸發了resolve或者reject,就直接返回了該狀態結果,並不在乎其成功或者失敗。
WeakRefs使用WeakRefs的Class類建立對物件的弱引用
當我們透過(const、let、var)建立一個變數時,垃圾收集器GC將永遠不會從記憶體中刪除該變數,只要它的引用仍然存在可訪問。而WeakRef物件包含對物件的弱引用,對物件的弱引用是不會阻止垃圾收集器GC恢復該物件的引用,則GC可以在任何時候刪除它,目前,可以透過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次了') } 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次了') } 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) //仍存在
WeakSet與Set相比有以下兩個區別
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之類的快取。
邏輯運算子和賦值表示式a ||= b//等價於a = a || (a = b)a &&= b//等價於a = a && (a = b)a ??= b//等價於a = a ?? (a = b)
??= 可用來初始化缺失的屬性
const pages = [ { title:'主要場景', path:'/' }, { path:'/a' }, { path:'/b' },]for (const page of pages){ page.title ??= '預設標題'}console.table(pages)//(index) title path//0 "主要場景" "/"//1 "預設標題" "/a"//2 "預設標題" "/b"
小結:
a ||= b:當a值不存在時,將b變數賦值給aa &&= b:當a值存在時,將b變數賦值給aa ??= b:當a值為null或者undefined時,將b變數賦值給a