[26] 強制轉型 - 隱含地 Boolean、運算子 || 、 &&


keywords:coercion boolean,運算子 || 、 &&

隱含地:Boolean

何種運算式的作業需要隱含地強制轉換為 boolean?

  1. 一個 if(..) 述句中的測試運算式
  2. 一個 for( .. ; .. ; .. ) 標頭中的測試運算式 ( 第二個子句 )
  3. while(..) 與 do..while(..) 迴圈中的測試運算式
  4. ? : 三元運算式中的測試運算式 ( 第一個句子 )
  5. || 和 && 運算子左邊的運算元

     let a = 99;
    
     let b = 'xyz';
    
     let c;
    
     let d = null;
    
     if(a){
    
       console.log('omg'); // omg
    
     }
    
     while(c){
    
       console.log('never run this');
    
     }
    
     c = d ? a : b;
    
     c; // 'xyz'
    
     if((a && d) || c){
    
       console.log('omg'); // omg
    
     }
    

運算子 || 與 &&

  • 這些運算子不應該被稱為邏輯的運算子,應該稱它們為選擇器運算子或更完整的是運算元選擇器運算子
  • 因為在 JS 裡面它們實際上並不會產生一個邏輯值,跟其他程式語言不同,它們會選擇兩個運算元其中一個的值
  • 引述 2021 規格的 12.13 Binary Logical Operators

    The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.
    && 或 || 運算子所產生的值不一定是 Boolean 型別,而是兩個運算元運算式其中一個的值

    let a = 98;

    let b = 'xyz';

    let c = null;

    a || b; // 98

    a && b; // 'xyz'

    c || b; // 'xyz'

    c && b; // null
  • && 與 || 運算子會在第一個運算元上進行 boolean 測試,如果該運算元尚不是 boolean 值,就會發生正常的 ToBoolean 強制轉型

  • || 運算子:第一個對就停下來取第一個

  • && 運算子:兩個都要對,所以第一個對就會取第二個

      a || b;   大略等同於:    a ? a : b
    
      null ? null : 99; // 99
    
      99 ? 99 : null; // 99
    
      a && b;   大略等同於:    a ? b : a
    
      null ? 99 : null; // null
    
      99 ? null : 99; // null
    
  • || 此種行為極為常見且相當有幫助的用法:

      function f1(a,b) {
    
        a = a || 'oh';
    
        b = b || 'my god!';
    
        console.log(a + ' ' + b);
    
      }
    
      f1(); // 'oh my god!'
    
      f1('hi','everyone!'); // 'hi everyone!'
    

    這種慣用法就是提供一個備用的預設值 ('oh'),但要小心
    f1('Game over!',''); // 'Game over! my god!'
    因為第二個引數的 '' 是一個 falsy 值 ( 還記得是哪五項 8 個嗎 ),所以 b = b || 'my god!' 會回傳 'my god!',即使這裡的意圖可能是真的明確要傳入 '' 作為指定給 b
    這個 || 慣用法極為普遍,也相當有幫助但只能在『 所有的 falsy 值都應該被跳過 』的情況下使用,否則你的測試就得更明確,或許要改用 ?: 三元運算子才是

  • && 有一個慣用手法較少手動使用,不過經常被 JS 縮小器所用,&& 運算子只在第一個運算元的測試結果是 truthy 時才會選擇第二個運算元 ( a ? b : a ),這種用法常被稱為守護運算子 ( guard operator )

      function f1() {
    
        console.log(a);
    
      }
    
      let a = 99;
    
      a && foo(); // 99
    
      f1() 只在 a 測試結果是 truthy 時被呼叫,如果測試失敗了就會安靜地停止,不會呼叫 f1()
    
      通常人們都會用:
    
      if(a){
    
        foo();
    
      }
    
      JS 縮小器會用:
    
      a && foo();
    
      let a = 99;
    
      let b = null;
    
      let c = 'xyz';
    
      if(a && ( b || c )){
    
        console.log('hi');  // 'hi'
    
      }
    
      實際上所產生的是 'xyz' 而非 true,只是 if 述句強制把 'xyz' 值轉型為一個 boolean
    

Symbol 的強制轉型

ES6 的 Symbol 為強制轉型系統引入了一個陷阱
var s1 = Symbol('hi');

非常少會遇到需要強制轉型一個 symbol

coercion symbol

#coercion boolean #運算子 || 、 &&







你可能感興趣的文章

[第十周] 有點難分的 Session 和 Cookie

[第十周] 有點難分的 Session 和 Cookie

深入學習 LSD-SLAM - 2

深入學習 LSD-SLAM - 2

Reactive Programming 簡介與教學(以 RxJS 為例)

Reactive Programming 簡介與教學(以 RxJS 為例)






留言討論