JavaScriptには「短絡」評価がありますか?


101

JavaScriptにC&Cの&&演算子のような「短絡」評価があるかどうか知りたいのですが。そうでない場合は、採用する意味のある回避策があるかどうかを知りたいです。


2
どういたしまして。https://www.google.com/search?q=site:stackoverflow.com+%s検索を高速化するために、検索ショートカット(Chrome / Firefox)として追加しました。
Rob W

また、ここで私の質問への答えdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
GibboK

さらに役立つリソース:|| 評価の質問 &&評価の質問
Samuel Hulla

回答:


117

はい、JavaScriptには「短絡」評価があります。

if (true == true || foo.foo){
    // Passes, no errors because foo isn't defined.
}

ライブデモ

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}

ライブデモ


8
だからそれはJSの標準です短絡?
GibboK 2012

1
ありがとうgdoronは、オペランドはCではなく&&で、渡すために真でなければならないC#で、私は二項演算子のように&両方のようにも持っている...私が理解する助けてください
GibboK

1
@GibboK。その場合、当然、Short-circuitその論理演算子を使用することはできません。自分で試してみてください。私のデモを使用してください。
gdoronはモニカサポートしている

2
@GibboK:この演算子リファレンスを確認してください。そして、はい、JSにもバイナリAND演算子があります。
Bergi、2012

5
@GibboK。標準でYES!しかし、良いコメントは、JavaScript実装におけるJITコンパイルマジックの時のように、何かが「標準」であるか、または実装の対象になる可能性があるかどうかを本当に知りたいと思っています。二項論理演算子を使用した条件ステートメントが評価され、(ショートカーソル)が標準的な動作になる方法ecma-international.org/ecma-262/5.1/#sec-11.11
humanityANDpeace

22

この答えは、 JavaScriptで動作し、すべての落とし穴や演算子の優先順位などの関連テーマも含まれます。簡単な定義を探していて、短絡がどのように機能するかをすでに理解している場合は、他の回答を確認することをお勧めします。


これまでに私たちが思っていたこと:

最初に、if()ブロック内で慣れ親しんでいる動作を調べて&&、2つの要素があるかどうかを確認しますtrue

if (true && true) {
   console.log('bar');
} 

:今、あなたの最初の本能は言っておそらく「ああ、はい、非常に簡単、コードが両方のif文を実行expr1し、expr2として評価されていますtrue

まあ、はい、いいえ。あなたは技術的に正しいです、それはあなたが説明した振る舞いですが、それは正確にコードが評価される方法ではなく、完全に理解するためにさらに深く掘り下げる必要があります。


どのように正確である&&||解釈は?:

「のフードの下で見る時が来ました エンジン」。この実用的な例を考えてみましょう:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

let userinput = 0xFF; // as an example
const res = sanitise(userinput) && userinput + 5

console.log(res);

まあ結果は260..ですが、なぜですか?答えを得るには、短絡評価の仕組みを理解する必要があります。

MDN定義により、 の&&演算子expr1 && expr2は次のように実行されます。

expr1に変換できる場合はをtrue返しますexpr2。それ以外の場合はを返しますexpr1

つまり、これは、実際の例でconst resは、次のように評価されることを意味します。

  1. 呼び出し中expr1-sanitise(0xFF)
  2. 0xFF 250の有効な16進数です。それ以外の場合は返されます NaN
  3. expr1「truthy」値、実行時間を返してexpr2 (そうでない場合は、私のように停止したいNaNfalsyです)
  4. 以来userinputtruthy(番号)ですが、私は追加することができ+5、それに
  • 「真実」とは、式を真として評価できることを意味します。これが真実偽りの 表現のリストです 。

そのため、ここでは、オペレーターを使用するだけで、追加のifブロックを回避し、さらにisNaNチェックすることができました&&


それが実際に機能する方法:

今までに、少なくともどのように 演算子が動作します。普遍的なルールは次のとおりです。

  • (some falsy expression) && expr 偽の表現に評価されます
  • (some truthy expression) || expr 真実の表現に評価されます

以下に、理解を深めるための例をいくつか示します。

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() && b() ){
     console.log('foobar'); 
}

//Evaluates a() as false, stops execution.

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() || b() ){
     console.log('foobar'); 
}

/* 1. Evaluates a() as false
   2. So it should execute expr2, which is `b()`
   3. b() returned as true, executing statement `console.log('foobar');`
*/


最後に厄介ですが、非常に重要なもの[演算子の優先順位]:

いいですね、うまくいけば、コツをつかむことができます!最後に知っておく必要があるのは、演算子の優先順位に関する規則です。

  • &&オペレータは、常に前に実行される||演算子。

次の例について考えてみます。

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log(a() || b() && c());

// returns a() and stops execution

これは、おそらく混乱するように、に戻りa()ます。理由は非常に単純です。左から右に読むことに慣れているため、私たちをだましているのは私たちの視力だけです。console.log()外に出ていないものを取り、純粋に評価に集中しましょう

true || false && false

これで頭を包みます:

  1. 私たちは言った&&、オペレータが優先され、それが最初のように評価されます。評価をよりよく想像するために、定義を考えてください

    expr1 && expr2

    どこ:

    • expr2 です false
    • expr1 です true || false
  2. これがトリッキーな部分だったので、true || false評価されます(expr1-の左側&&)。

    • 与えられた||ならば、オペレータは実行を停止するexpr1 || expr2expr1truthyとして評価し、expr1実行され、コードの実行が停止されます。
  3. 戻り値は true

まあ..いくつかの奇妙なルールとセマンティクスのために、それはかなりトリッキーでした。しかし、覚えておいてください()- 数学のように、演算子の優先順位はいつでもエスケープできます-

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log((a() || b()) && c());

/* 1. The () escape && operator precedence
   2. a() is evaluated as false, so expr2 (c()) to be executed
   3. c()  
*/


1)「コンパイラ」という言葉は使わない。「エンジン」はより正確です。2)について話をしないexpr1expr2condition1または何でも、ちょうど混乱しています。たとえば、ローカル変数を導入することもできます。const expr1 = true; if(expr1 && ...)
Jonas Wilms

@JonasWilmsは入力に感謝し、それに応じて回答を修正しました。
Samuel Hulla

1
これはまだ尋ねられた質問に直接答えません。
Kevin B

7
これは、私が今まで見た中で最高の「質問に明確に答えない素晴らしい答え」です...
ジェラルド

1
これは正しい説明であり、深い説明があります。現在よりもはるかに多く受け入れられ、賛成されている必要があります。
Alexander Kim
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.