看了這兩篇,ECMAScript12你就懂了(二)
三、??= ?&&= ?||=
??=(邏輯空賦值運(yùn)算符 (x ??= y) 僅在 x 是 nullish (null 或 undefined) 時(shí)對(duì)其賦值。)
ES11提出了空值合并運(yùn)算符??(空值合并操作符(??)是一個(gè)邏輯操作符,當(dāng)左側(cè)的操作數(shù)為 null 或者 undefined 時(shí),返回其右側(cè)操作數(shù),否則返回左側(cè)操作數(shù)。)
const?foo?=?null????'default?string';
console.log(foo);?//?default?string
而??=,也從這個(gè)基礎(chǔ)上又出了這個(gè)??=
const?a?=?{?duration:?50?};
a.duration???=?10;
console.log(a.duration);
//?50
a.speed???=?25;
console.log(a.speed);
//?25
空值合并運(yùn)算符從左至右求值。(結(jié)果非 null 或 undefined 的表達(dá)式) ?? expr 被短路求值為左側(cè)表達(dá)式,當(dāng)左側(cè)證明為既非 null 也非 undefined.
語(yǔ)法短路意味著 expr 部分尚未被求值,因此任何與其求值產(chǎn)生的相關(guān)副作用都不會(huì)生效(例如,如果 expr 是一個(gè)函數(shù)調(diào)用,則該調(diào)用將不會(huì)發(fā)生)。
邏輯空賦值的語(yǔ)法短路也意味著 x ??= y 等價(jià)于:
x????(x?=?y);?//?理解空值合并運(yùn)算符之后,再理解就簡(jiǎn)單啦。
x?=?x????(x?=?y)
&&=((x &&= y) 僅在 x 是 truthy (非假值,前面有介紹過(guò)<即除 false、0、""、null、undefined 和 NaN 以外皆為真值>) 時(shí)對(duì)其賦值。)
let?a?=?1;
let?b?=?0;
a?&&=?2;
console.log(a);
//?2
b?&&=?2;
console.log(b);
//?0
x &&= y 等價(jià)于:
x?&&?(x?=?y);?
x?=?x?&&?(x?=?y)
||=((x &&= y) 僅在 x 是 falsy (假值<即false、0、""、null、undefined 和 NaN>) 時(shí)對(duì)其賦值。)
const?a?=?{?duration:?50,?title:?''?};
a.duration?||=?10;
console.log(a.duration);
//?expected?output:?50
a.title?||=?'title?is?empty.';
console.log(a.title);
//?"title?is?empty"
x ||= y 等價(jià)于:
x?||?(x?=?y);?
x?=?x?||?(x?=?y)
四、數(shù)字分隔符允許數(shù)值字面量中間包含不連續(xù)_ ,以提高可讀性。
1_000_000_000???????????//?1000000000
101_475_938.38??????????//?101475938.38
let?a?=?1_1;?//?11
let?a?=?1__1?//?錯(cuò)誤,只允許一個(gè)下劃線作為數(shù)字分隔符
let?a?=?1_;??//?錯(cuò)誤,分隔符不能在尾部?
let?a?=?_1;??//?錯(cuò)誤,分隔符不能在頭部?
Number(1_1);?//?11
Number('1_1');?//?NaN
注意:分隔符不能在尾部和頭部,只能在數(shù)字之間,只允許一個(gè)下劃線作為數(shù)字分隔符,不可連續(xù)。
五、WeakRefs & FinalizationRegistryWeakRef對(duì)象包含對(duì)對(duì)象的弱引用,這個(gè)弱引用被稱(chēng)為該WeakRef對(duì)象的target或者是referent。對(duì)對(duì)象的弱引用是指當(dāng)該對(duì)象應(yīng)該被GC回收時(shí)不會(huì)阻止GC的回收行為。而與此相反的,一個(gè)普通的引用(默認(rèn)是強(qiáng)引用)會(huì)將與之對(duì)應(yīng)的對(duì)象保存在內(nèi)存中。只有當(dāng)該對(duì)象沒(méi)有任何的強(qiáng)引用時(shí),JavaScript引擎GC才會(huì)銷(xiāo)毀該對(duì)象并且回收該對(duì)象所占的內(nèi)存空間。如果上述情況發(fā)生了,那么你就無(wú)法通過(guò)任何的弱引用來(lái)獲取該對(duì)象。
Note: 對(duì)于WeakRef對(duì)象的使用要慎重考慮,能不使用就盡量不要使用
為什么盡量避免使用
正確使用WeakRef對(duì)象需要仔細(xì)的考慮,最好盡量避免使用。避免依賴于規(guī)范沒(méi)有保證的任何特定行為也是十分重要的。何時(shí)、如何以及是否發(fā)生垃圾回收取決于任何給定JavaScript引擎的實(shí)現(xiàn)。GC在一個(gè)JavaScript引擎中的行為有可能在另一個(gè)JavaScript引擎中的行為大相徑庭,或者甚至在同一類(lèi)引擎,不同版本中GC的行為都有可能有較大的差距。GC目前還是JavaScript引擎實(shí)現(xiàn)者不斷改進(jìn)和改進(jìn)解決方案的一個(gè)難題。
let obj = {a:1, b:2}; // 只要我們?cè)L問(wèn) obj 對(duì)象,這個(gè)對(duì)象就不會(huì)被垃圾回收
Weakref 實(shí)例具有一個(gè)方法 deref,該方法返回被引用的原始對(duì)象,如果原始對(duì)象已被收集,則返回 undefined 對(duì)象。
const?ref?=?new?WeakRef({?name:?'前端編程之家'?});
let?obj?=?ref.deref();
if?(obj)?{
??console.log(obj.name);?//?前端編程之家
}?else{
??console.log('target?deleted!')
}
FinalizationRegistry 提供了這樣的一種方法:當(dāng)一個(gè)在注冊(cè)表中注冊(cè)的對(duì)象被回收時(shí),請(qǐng)求在某個(gè)時(shí)間點(diǎn)上調(diào)用一個(gè)清理回調(diào)。(清理回調(diào)有時(shí)被稱(chēng)為 finalizer )。
使用 FinalizationRegistry 對(duì)象可以在垃圾回收器回收對(duì)象時(shí)執(zhí)行回調(diào)函數(shù)。
//?構(gòu)建監(jiān)聽(tīng)對(duì)象被垃圾回收器清除的回調(diào)
const?registry?=?new?FinalizationRegistry(heldValue?=>?{
??????console.log('----',?heldValue);
});
const?obj?=?{};
const?token?=?{};
//?注冊(cè)監(jiān)聽(tīng)
registry.register(obj,?"obj?deleted!",?token);
//?取消監(jiān)聽(tīng)
registry.unregister(token);
//?----?obj?deleted!
register 參數(shù)分別為:需要監(jiān)聽(tīng)的對(duì)象、 執(zhí)行回調(diào)函數(shù)的參數(shù)、 取消監(jiān)聽(tīng)用的標(biāo)識(shí)符
