JavaScript での短絡


JavaScript では、短絡とは、不要な計算を避けるために式を部分的に評価することを指します.このブログ投稿では、JavaScript の短絡演算子と割り当て、およびそれらの使用方法について説明します.

短絡演算子: &&、||、および ??



短絡演算子は、必要な場合にのみ式の右側を評価します.

たとえば、論理 AND 演算子 && の場合、演算子の左側が false の場合、演算子の右側は結果を変更しません.右辺が真か偽かに関係なく、結果は偽です.したがって、JavaScript は右側の評価をスキップし、左側の値を使用します.

JavaScript には、短絡二項演算子が 3 つあります.

  • Logical AND ( A && B ): B は、 Atruthy の場合にのみ評価されます.

  • Logical OR ( A || B ): B は、 Afalsy の場合にのみ評価されます.

  • Nullish coalescing ( A ?? B ): B は、 Anullish の場合にのみ評価されます.
  • A および B は、任意の式にすることができます.それらの評価は、複雑な計算を含んだり、副作用を持つ可能性のある関数や getter 呼び出しを呼び出す可能性があります.AB は任意の値を返すことができるため、3 つの短絡演算子はブール値だけでなく任意の値を評価して返します.

    つまり、短絡演算子を使用して、デフォルト値 ( || および ?? ) を提供したり、null 値をチェックしたり (オプションのチェーン演算子 && が使用可能になる前は ?. )、および conditional rendering in React ( && ) を使用したりできます.

    // default values
    a = a || 123; // assigns 123 to a if a is falsy
    b = b ?? 123; // assigns 123 to b if b is nullish
    
    // optional chaining with && ( .? is a modern alterative)
    if (obj.m != null && obj.m() === '123') {
       // ...
    }
    
    // React: conditional rendering
    return <>  
      {user != null &&
        <div>Welcome back, ${user.name}!</div>
      }
    <>;
    


    短絡割り当て: &&=、||=、および ??=



    ES2021 では、代入式で短絡演算子を使用できます ( &&=||= 、および ??= ).短絡割り当ては、現在の変数またはプロパティ値が短絡をトリガーしない場合にのみ実行されます.この動作は、不要な更新を避けるのに役立ちます.

    以下に例を示します ( -Infinitytruthy です).

    let a = 3;
    let b = 3;
    let c = 0;
    let d = 0;
    
    a &&= -Infinity;
    b ||= -Infinity;
    c &&= -Infinity;
    d ||= -Infinity;
    
    console.log(a); // -Infinity
    console.log(b); // 3 (short-circuiting ||, because 3 is truthy)
    console.log(c); // 0 (short-circuiting &&, because 0 is falsy)
    console.log(d); // -Infinity
    


    短絡演算子を使用した代入のリファクタリング



    短絡代入は、短絡演算子式を使用した通常の代入と非常によく似ています.動作を変更せずに、次のようにリファクタリングできると考える人もいるかもしれません.

    a = a && x; /* becomes */ a &&= x;
    a = a || x; /* becomes */ a ||= x;
    a = a ?? x; /* becomes */ a ??= x;
    


    しかし、私が安全性評価を開発していたとき、
    ' Push Operator into Assignment ' および ' Pull Operator Out of Assignment ' のリファクタリングを P42 で行ったところ、これらのリファクタリングが状況によっては動作の変化につながる可能性があることがわかりました.

    次の例を検討してください.

    class C {
      constructor(name) {
        this.name = name;
      }
    
      get x() {
        return this._x;
      }
    
      set x(value) {
        console.log(`set ${this.name}.x to ${value}`);
        this._x = value;
      }
    }
    



    // nullish coalescing operator
    const a = new C("a");
    a.x = a.x ?? 3;
    a.x = a.x ?? 4;
    console.log(a.x)
    



    // nullish assignment 
    const b = new C("b");
    b.x ??= 3;
    b.x ??= 4;
    console.log(b.x)
    


    驚いたことに、演算子を割り当てに移動すると、実行される操作が変わります.

    // output for nullish coalescing operator
    "set a.x to 3"
    "set a.x to 3"
    3
    



    // output for nullish assignment 
    "set b.x to 3"
    3
    


    ほとんどの場合、これらの小さな違いは重要ではありませんが、次の 2 つの理由から知っておくとよいでしょう.
  • 既存の動作を変更するため、リファクタリング中に破損が発生する可能性がある
  • パフォーマンスのホットスポットでの操作の数を減らすのに役立ちます

  • 概要



    JavaScript の短絡演算子 ( &&||?? ) は、必要な場合にのみ右側の式を評価します.それらに相当する割り当て ( &&=||=??= ) は、現在の値が更新される場合にのみ値を更新します.
    短絡演算子の右側が実行されます.