今晚我想來點 nullish coalescing operator
type coercion
一般寫程式的時候像在跟機器講話,而且他們通常邏輯比你好,又脾氣不太好。
機器:「你要不要吃晚餐?」
Richard:「今晚我想來點兇巴巴的起司牛肉可頌」
機器:「伶杯是先問你要不要吃?還沒問你吃什麼?」
幸運的是,在 javascript 這個語言中,機器個性稍微的隨和一點。他看你有回答晚餐的名字,就當你要吃晚餐,所以接著把你的晚餐顯示在螢幕上。
const dinnerOfRichard = '起司牛肉可頌' //我回答「起司牛肉可頌」
//機器決定要顯示什麼
const coercion = (dinnerOfPerson) => {
//如果dinnerOfPerson沒有東西,也就是null、undefined或空字串,javascript就會把它視為false
if(dinnerOfPerson){
console.log('是的你晚上要吃晚餐,而且要吃:',dinnerOfRichard)
} else {
console.log('你不吃晚餐')
}
}
coercion(dinnerOfRichard);//螢幕顯示「是的你晚上要吃晚餐,而且要吃:起司牛肉可頌」
const dinnerOfJolin = ''//Jolin沒有回答
coercion(dinnerOfJolin);//螢幕顯示「你不吃晚餐」
如果你不回答,或是回答不吃(false 、0 、空字串、null 、undefined) ,機器也都可以接受這些答案,並且依照你計畫的顯示:「你不吃晚餐」,機器心理會想著「既然你沒有說食物的名字,那麼我就當你不吃晚餐好了。」
這就稱為 coalescing。
這也是為什麼有人認為 javascript 的 type coercion太隨便了,如果寫出有 bug 的程式,會不容易把bug 找出來。但是另一方面來想,這是 javascript 的一個重要的特色,可以讓程式碼很簡短,又很符合人類的思考方式。
type coercion 在 javscript 裡面應用的很廣,例如「且」和「或」的邏輯運算上。
「且」和「或」
「且」和「或」不但是機器很常用的邏輯,人類也很常用,例如這段程式碼:
const isGangGoing = true; //小剛要去爬山
const isXienGoing = true; //小嫺要去爬山
//機器決定我是否去爬山
const wantHiking = (isGangGoing,isXienGoing)=>{
if(isGangGoing && isXienGoing) {
console.log('好,我去爬山')
} else {
console.log('我不去爬山')
}
}
wantHiking(isGangGoing,isXienGoing);
//螢幕顯示「好,我去爬山」
翻譯成人類的語言就是:以 && 為界線,如果左邊的小剛要去爬山 (isGangGoing) ,而且 (&&) ,右邊的小嫺要去爬山 (isXienGoing) 的話,兩個條件同時成立的話,我就去爬山,否則,我就不去爬山。
如果程式碼裡面的 && (且)改成 || (或),這段程式翻譯成人類的語言就會變成:如果左邊的小剛要去爬山,或 (||) ,右邊的小嫺要去爬山,任何一個條件成立,我就去爬山,否則,我就不去爬山。
我覺得很有意思的一個地方是 javascript 的 && 和 || ,用和我們人類一般直覺不一樣的思考方式來得到一樣的結果, && 的部分 JS 的思考方式翻譯成人類語言變成:
如果小剛要去爬山 (isGangGoing 是 true) 的話,就讓小嫺要不要去爬山 (isXienGoing 是 true 或 false),來決定我要不要去爬山。也就是小嫺去爬我就去爬山,否則,我就不去爬山。如果小剛不要去爬山的話 ( isGangGoing 是 true) ,不管小嫺要不要去爬山 (isXienGoing是 true 或 false) ,我都不會去爬山。
|| 的部分就變成:
如果小剛要去爬山的話,那我就一定會去爬山,不管小嫺要不要去爬山。如果小剛不要去爬山的話,才是小嫺要不要去爬山來決定我要不要去爬山,小嫺去爬我就去爬山,否則,我就不去爬山。
對於「且」和「或」,JS語言和人類判斷和思考過程不同,但是結果卻是一樣的。 JS 的判斷過程:
- 條件1 && 條件2,代表的意思是如果 && 左邊為 true ,就回傳右邊 (也就是條件2) ;左邊為 false 就回傳左邊。
- 條件1 || 條件2,代表的意思是如果 || 左邊是 true ,就回傳左邊 (條件1) ;左邊是 false ,就回傳右邊 (條件2) 。
JS的判斷結果:
- 條件1 && 條件2 => 兩個都 true 才是 true ,一個是 false 就是 false 了。
- 條件1 || 條件2 => 兩個其中有一個 true 就是 true ,兩個都 false 才是 false 。
如果配合一開始提到的 type coercion , && 和 || 的左右兩側的變數不一定要放 true 和 false 這種非黑即白的條件,可以是「起司牛肉可頌」這種答案,意思是Richard否定、空白、沒有Richard這個人 (false, null, undefined, 0, 空字串) 會被當成 false,其他答案會被當成 true。
最精彩的地方是,他判斷完 true 和 false 之後,回傳的不是 true 或 false ,而是裡面是什麼直接回傳什麼,例如直接回傳「起司牛肉可頌」這個答案。之所以用這種方式來判斷,是因為又可以讓程式更變態的精簡了,例如以下的寫法:
let dinnerOfJolin = `起司牛肉可頌` //Jolin要吃「起司牛肉可頌」
//機器把點的餐顯示在螢幕上
const coercion = (dinnerOfPerson) => {
console.log(dinnerOfPerson && `今晚來點${dinnerOfPerson}`)
}
coercion(dinnerOfJolin); //螢幕顯示「今晚來點起司牛肉可頌」,因為Jolin有點餐
dinnerOfJolin = ``//Jolin什麼都沒說
coercion(dinnerOfJolin);//螢幕不會出現「今晚來點」,而是什麼都不會出現
翻譯成人類的語言就是,如果 dinnerOfJolin 有點東西的話 (起司牛肉可頌) ,就判斷為 true ,然後回傳 && 右邊,直接顯示「今晚來點起司牛肉可頌」,沒東西的話,就什麼都沒顯示,因為是回傳&&左邊,也就是 dinnerOfJolin 。
反之 || 的使用情況是這樣
let dinnerOfJolin = `` //Jolin什麼話都沒說
//機器把Jolin點的餐顯示在螢幕上
const coercion = (dinnerOfJolin) => {
console.log(dinnerOfJolin || `Jolin沒點餐喔`)
}
coercion(dinnerOfJolin);//螢幕出現「Jolin沒點餐喔」
dinnerOfJolin = `今晚來點起司牛肉可頌`//Jolin說「今晚來點起司牛肉可頌」
coercion(dinnerOfJolin);//螢幕出現「今晚來點起司牛肉可頌」
翻譯成人類的語言就是,如果 dinnerOfJolin 裡面沒有東西的話,就判斷為 false ,然後直接 顯示||右邊的「 Jolin 沒點餐喔」,裡面有東西的話 (起司牛肉可頌) ,就直接顯示 || 左邊的「今晚來點」和「起司牛肉可頌」。
nullish coalescing operator
讀到這裡,相信我們已經非常了解 && ||是什麼和怎麼用,那麼 ES2020 的 ?? (nullish coalescing operator) 就不難了,簡單來說,他只是用來在特殊場合取代 || 的。
例如: 機器問:「晚餐你要付多少錢?」
我原本希望電腦螢幕在我厚臉皮回答 0 的時候顯示「0」,我沒回答的時候顯示「你還沒回答」。
但是 JS 原本的 || 的程式碼無法達成我想要的效果,例如以下程式碼:
let payOfRichard=0 //我回答0
//機器顯示我要付多少錢
const coercion = (payOfRichard) => {
console.log(payOfRichard || `你還沒回答`)
}
coercion(payOfRichard)//螢幕顯示「你還沒回答」
上面會顯示「你還沒回答」,這不是我們想要的,我們希望螢幕顯示「0」。這時後,我們把 || 改成 ?? 就心想事成了,如下面的程式看得出來,我什麼都還沒說,顯示的就是「你還沒回答」。
let payOfRichard; //我什麼都還沒說
//機器顯示我要付多少錢
const nco = (payOfRichard) => {
console.log(payOfRichard ?? `你還沒回答`)
}
nco(payOfRichard) //顯示「你還沒回答」
payOfRichard=0 //我回答0
nco(payOfRichard) //顯示「0」
payOfRichard=100
nco(payOfRichard) //顯示「100」
有了 nullish coalescing operator,我們碼農又可以用更簡短的程式,命令機器對付更複雜的情況了。這裡簡單提供一下可能應用的三種使用情況:
- 想要沒有值的時候什麼都不顯示,有值的時候顯示值,就用 && 。
- 想要沒有值或值是 0 的時候,顯示預設的訊息,有值的時候顯示值,就用 || 。
- 想要沒有值的時候顯示預設訊息,有值的時候,不管值是 0 或不是 0 ,都要顯示值,就用 ?? 。
講到這裡剛好想到機器這樣的思考方式,其實在人類生活中也可能遇到,例如以前我在洽談專利案件時,某些公司老闆要辦專利,最好談案件時邀請他夫人一起了解,因為通常老闆找你來談案件的時候是已經決定要辦了,但是管錢的夫人還沒同意,我們剛學到的機器思考老闆 && 老闆娘
的方式就用上了,成交與否其實和老闆娘的關係比較大,讓董娘也了解什麼是專利,為什麼要申請專利,成交的機率似乎較大。