JavaScript 的這 4 個(gè)運(yùn)算符,讓代碼更干凈簡(jiǎn)潔!??!
ECMAScript 發(fā)展進(jìn)程中,會(huì)有很多功能的更新,比如銷(xiāo)毀,箭頭功能,模塊,它們極大的改變 JavaScript 編寫(xiě)方式,可能有些人喜歡,有些人不喜歡,但像每個(gè)新功能一樣,我們最終會(huì)習(xí)慣它們。
新版本的 ECMAScript 引入了三個(gè)新的邏輯賦值運(yùn)算符:空運(yùn)算符,AND 和 OR 運(yùn)算符,這些運(yùn)算符的出現(xiàn),也是希望讓我們的代碼更干凈簡(jiǎn)潔,下面分享幾個(gè)優(yōu)雅的 JavaScript 運(yùn)算符使用技巧。
一、可選鏈接運(yùn)算符【?.】
可選鏈接運(yùn)算符(Optional Chaining Operator) 處于 ES2020 提案的第 4 階段,因此應(yīng)將其添加到規(guī)范中。它改變了訪(fǎng)問(wèn)對(duì)象內(nèi)部屬性的方式,尤其是深層嵌套的屬性。它也可以作為 TypeScript 3.7 + 中的功能使用。
相信大部分開(kāi)發(fā)前端的的小伙伴們都會(huì)遇到 null 和未定義的屬性。JS 語(yǔ)言的動(dòng)態(tài)特性使其無(wú)法不碰到它們。特別是在處理嵌套對(duì)象時(shí),以下代碼很常見(jiàn):
if (data && data.children && data.children[0] && data.children[0].title) {
// I have a title!
}
上面的代碼用于 API 響應(yīng),我必須解析 JSON 以確保名稱(chēng)存在。但是,當(dāng)對(duì)象具有可選屬性或某些配置對(duì)象具有某些值的動(dòng)態(tài)映射時(shí),可能會(huì)遇到類(lèi)似情況,需要檢查很多邊界條件。
這時(shí)候,如果我們使用可選鏈接運(yùn)算符,一切就變得更加輕松了。它為我們檢查嵌套屬性,而不必顯式搜索梯形圖。我們所要做的就是使用 “?” 要檢查空值的屬性之后的運(yùn)算符。我們可以隨意在表達(dá)式中多次使用該運(yùn)算符,并且如果未定義任何項(xiàng),它將盡早返回。
對(duì)于靜態(tài)屬性用法是:
object?.property
對(duì)于動(dòng)態(tài)屬性將其更改為:
object?.[expression]
上面的代碼可以簡(jiǎn)化為:
let title = data?.children?.[0]?.title;
然后,如果我們有:
let data;
console.log(data?.children?.[0]?.title) // undefined
data = {children: [{title:'codercao'}]}
console.log(data?.children?.[0]?.title) // codercao
這樣寫(xiě)是不是更加簡(jiǎn)單了呢?由于操作符一旦為空值就會(huì)終止,因此也可以使用它來(lái)有條件地調(diào)用方法或應(yīng)用條件邏輯
const conditionalProperty = null;
let index = 0;
console.log(conditionalProperty?.[index++]); // undefined
console.log(index); // 0
對(duì)于方法的調(diào)用你可以這樣寫(xiě)
object.runsOnlyIfMethodExists?.()
例如下面的parent對(duì)象,如果我們直接調(diào)用parent.getTitle(), 則會(huì)報(bào)Uncaught TypeError: parent.getTitle is not a function錯(cuò)誤,parent.getTitle?.()則會(huì)終止不會(huì)執(zhí)行
let parent = {
name: "parent",
friends: ["p1", "p2", "p3"],
getName: function() {
console.log(this.name)
}
};
parent.getName?.() // parent
parent.getTitle?.() //不會(huì)執(zhí)行
與無(wú)效合并一起使用
提供了一種方法來(lái)處理未定義或?yàn)榭罩岛捅磉_(dá)提供默認(rèn)值。我們可以使用??運(yùn)算符,為表達(dá)式提供默認(rèn)值
console.log(undefined ?? 'codercao'); // codercao
因此,如果屬性不存在,則可以將無(wú)效的合并運(yùn)算符與可選鏈接運(yùn)算符結(jié)合使用以提供默認(rèn)值。
let title = data?.children?.[0]?.title ?? 'codercao';
console.log(title); // codercao
二、邏輯空分配(?? =)
expr1 ??= expr2
邏輯空值運(yùn)算符僅在 nullish 值(null 或者 undefined)時(shí)才將值分配給 expr1,表達(dá)方式:
x ??= y
可能看起來(lái)等效于:
x = x ?? y;
但事實(shí)并非如此!有細(xì)微的差別。
空的合并運(yùn)算符(??)從左到右操作,如果 x 不為 nullish 值則中表達(dá)式不執(zhí)行。因此,如果 x 不為null 或者 undefined,則永遠(yuǎn)不會(huì)對(duì)表達(dá)式y(tǒng)進(jìn)行求值。如果y是一個(gè)函數(shù),它將根本不會(huì)被調(diào)用。因此,此邏輯賦值運(yùn)算符等效于
x ?? (x = y);
三、邏輯或分配(|| =)
此邏輯賦值運(yùn)算符僅在左側(cè)表達(dá)式為 falsy 值(虛值) 時(shí)才賦值。Falsy 值(虛值)與 null 有所不同,因?yàn)?falsy 值(虛值)可以是任何一種值:undefined,null,空字符串 (雙引號(hào) ""、單引號(hào)’’、反引號(hào) ``),NaN,0。IE 瀏覽器中的 document.all,也算是一個(gè)。
語(yǔ)法
x ||= y
等同于
x || (x = y)
在我們想要保留現(xiàn)有值(如果不存在)的情況下,這很有用,否則我們想為其分配默認(rèn)值。例如,如果搜索請(qǐng)求中沒(méi)有數(shù)據(jù),我們希望將元素的內(nèi)部 HTML 設(shè)置為默認(rèn)值。否則,我們要顯示現(xiàn)有列表。這樣,我們避免了不必要的更新和任何副作用,例如解析,重新渲染,失去焦點(diǎn)等。我們可以簡(jiǎn)單地使用此運(yùn)算符來(lái)使用 JavaScript 更新 HTML:
document.getElementById('search').innerHTML ||= '<i>No posts found matching this search.</i>'
四、邏輯與分配(&& =)
可能你已經(jīng)猜到了,此邏輯賦值運(yùn)算符僅在左側(cè)為真時(shí)才賦值。因此:
x &&= y
等同于
x && (x = y)
本次分享幾個(gè)優(yōu)雅的 JavaScript 運(yùn)算符使用技巧,重點(diǎn)分享了可選鏈接運(yùn)算符的使用,這樣可以讓我們不需要再編寫(xiě)大量我們例子中代碼即可輕松訪(fǎng)問(wèn)嵌套屬性。但是 IE 不支持它,因此,如果需要支持該版本或更舊版本的瀏覽器,則可能需要添加 Babel 插件。對(duì)于 Node.js,需要為此升級(jí)到 Node 14 LTS 版本,因?yàn)?12.x 不支持該版本。
作者:前端開(kāi)發(fā)愛(ài)好者
歡迎關(guān)注微信公眾號(hào) :前端開(kāi)發(fā)愛(ài)好者
添加好友備注【進(jìn)階學(xué)習(xí)】拉你進(jìn)技術(shù)交流群