iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 13
1
自我挑戰組

你為什麼不問問神奇 JavaScript 呢?系列 第 13

Day13 - 運算子優先序

這部分,克服JS奇怪的地方,真的講得很好。
這邊先嘗試用不同方法解決書上開的難題。

請看懂這張表,就能快速了解這幾個章節。

  1. 等級越高的先抓。
  2. 同等級的看他是 從左到右 ( Left to Right ) 還是 從右到左( Right to Left )。
  3. 搭配強制轉型結算

書上就是這題摟!

var a = 42;
var b = "foo";
var c = false;

var d = a && b || c ? c || b ? a : c && b : a;
d;  // ???

來試試看吧!

  1. 總結運算子,有三個, &&||? : :
  2. 查表,得到 &&=> 6, ||=> 5, ? : : => 4
  3. 先抓 && 是 L2R,結算 a && b = "foo"c && b = false
  4. 重整 "foo" || c ? c || b ? a : false : a;
  5. 再抓 || 是 L2R,結算 "foo" || c = "foo"c || b = "foo"
  6. 重整 "foo" ? "foo" ? a : false : a;
  7. 最後抓 ? : : 是 R2L,結算 "foo" ? a : false = a"foo" ? a : a = 42
  8. 回傳 42

但是書上的方法,比較簡潔。

  1. 優先性 ( 找進入點 )
  2. 繫結 ( 畫出肯定先做完的範圍 )
  3. 結合性 ( 確定執行方向 )

就變成書上的執行結果了。

a. 先依照優先性,把優先運算的地方匡起來。

(a && b) || c ? (c || b) ? a : (c && b) : a;

b. 再依照繫結,把相鄰的處理好。

[(a && b) || c ]? (c || b) ? a : (c && b) : a; // 標示用,不能執行

c. 最後處理結合性。

[(a && b) || c ]? [(c || b) ? a : (c && b)] : a; // 標示用,不能執行

接著就照著正常思維判斷

  1. a && b || c => "foo" || c => "foo"。truthy!
  2. 解決 ( c || b ) ? a : ( c && b )
  3. c || b => "foo"。 truthy!
  4. a = 42

消除歧異

但是,Tony 真的需要用小小腦袋排出整個流程,只為了得到一個 42?

寫出能夠一眼看出順序的 code 是很重要的。請善用 () 手動歸組。
同樣的式子,多了括號,可以少死很多腦細胞。

自動分號

JavaScript 的 ASI ( Automatic Semicolon Insertion,自動分號插入 )

ASI 的功能是防止 Tony 不小心沒放上分號。

  • ASI 只會在一個 newline ( 即 line break,換行 ) 出現時發生,不會插入一行文字。

只有在某個述句的結尾,和該行的 newline/line break 之間除了空白 (whitespace) 與註解 (comments) 之外,沒有其他的東西,才會插入。

  • do..while 常會忘記放,他會幫上忙

  • 述句區塊 {} 不需要 ; 終結,所以 ASI 沒差。

  • ASI 需要注意的地方是在使用 break,continue,return 以及 (ES6) yeild 關鍵字的時候。

function foo(a){
    if (!a) return
    a *= 2;
    // ..
}

錯誤更正

是目前為止,可以當故事看,放鬆的地方之一。

結論是

請在每個述句的結尾加上分號。謝謝。

switch

他可以有效地取代有許多 if else 的場景。

但要注意會需要在每個 case 下加上 break;。否則會執行後續的程式碼。

var a = 3;
switch (a) {
    case 1:
        console.log("Tony");
    case 2:
        console.log("你好");
    case 3: 
        console.log("你真的");
    default:
        console.log("沒有");
    case 4:
        console.log("很帥");
}
// 你真的
// 沒有
// 很帥

雖然說 default 不一定要放在最後(慣例是放最後,也符合語意)。
原本期望是能夠忽略 default 拿到 “你真的很帥”。結果是全部都會加進去。
switch 在使用上要記得加上 break。

這邊需要注意的是,每個 case 與 a 其實是嚴格相等 ===

那如果我想要用 == 來運算呢?需要一點 hack。

var a = "42"
switch (true) {
    case a == 10:
        console.log( "10 or '10'");
        break;
    case a == 42:
        console.log( "42 or '42'" );
        break;
    default:
        // something();
}

// 42 or '42'

值得注意的是,如果裡面是 truthy,是不會進入 case 的。
但你依然可以使用 !! 讓他變成 true

總結

  • 優先表可以幫你理清條理,書上的規則能幫忙快速判斷。
  • 不要仰賴自動分號。
  • 了解 switch 的規則。break 和 ===。

明天見!

參考資料

  1. 你所不知道的 JS
  2. 克服JS奇怪的地方
  3. MDN - Operator Precedence( 運算子優先順序表 )

上一篇
Day12 - 文法
下一篇
Day 14 - 錯誤訊息
系列文
你為什麼不問問神奇 JavaScript 呢?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言