JavaScript OR(||)変数割り当ての説明


351

このJavaScriptのスニペットを考えると...

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f = a || b || c || d || e;

alert(f); // 4

誰かがこのテクニックの名前を教えてくれませんか(私の質問はこの質問のタイトルにあると思います!)そしてそれはどのように/なぜ正確に機能するのですか?

私の理解では、変数fには最初の変数の最も近い値(左から右へ)が割り当てられ、nullでも未定義でもない値が割り当てられますが、この手法に関する多くの参照資料を見つけることができず、それがたくさん使われたのを見た。

また、この手法はJavaScriptに固有のものですか?PHPで同様のことを行うと、それ自体fの値ではなく、真のブール値が得られることがわかっていdます。


4
古い質問ですが、PHPに関しては、使用できる構成があります$f=$a or $f=$b or $f=$c; // etc。PHPには||演算子と演算子の両方orがあり、同じ働きをします。しかし、or評価された後、割り当てしばらくは||前に評価されます。これはまた、あなたに次の真のスタイルを与えます$a=getSomething() or die('oops');
Manngo

1
PHP 5.3では、あなたはまた少し短く、このような何かにカットすることができます...それから基づかせ三項演算子の中央部分を残すことができます: $f = $a ?: $b ?: $c;
レイ

1
PHP 7以降??、これに使用できます。$a = $b ?? 'default'
スペンサーラスキン

@SpencerRuskinなのでif $aの値がtrueに割り当てられます。$b$b'default'
oldboy

そのとおり。このページのnull合体演算子セクションをご覧ください:php.net/manual/en/migration70.new-features.php
Spencer Ruskin

回答:


212

説明については、短絡評価を参照してください。これらの演算子を実装する一般的な方法です。JavaScriptに固有のものではありません。


57
すべてが未定義、nullまたはfalseであっても、最後のものが常に割り当てられるという「gotcha」に注意してください。チェーンの最後で、false、null、または未定義ではないことがわかっているものを設定することは、何も見つからなかったことを示す良い方法です。
エリック・レッペン、2011

私はこのテクニックを何年も見てきましたが、使用したいと思ったときに私が驚いたのは、式の結果がブール値にキャストされないことです。後で行うことはできませんif( true == f )。整数がfに格納されている場合、このテストは常にfalseを返します。

9
実際にif(true == f)は、と同じです。これはif(f)、テストに合格することと同じです。のタイプもテストする場合はf、厳密な比較を使用しますif(true === f)。これは実際に失敗します。
Alsciende

5
はい、短絡評価は一般的です。ただし、ここでの違いは、JavaScriptが実行を停止した最後の値を返す方法にあります。@Anuragの答えは、これを説明する上ではるかに優れています。
Ben.12 2017

それが初心者にとって最良の説明かどうかはわかりません。お勧めします:javascript.info/logical-operators
csguy

198

これは、変数が偽の場合、デフォルト値、この場合はの値を割り当てるために行われますyx

JavaScriptのブール演算子はオペランドを返すことができ、他の言語のように常にブール結果を返すとは限りません。

論理OR演算子(||)は、最初のオペランドが偽である場合は2番目のオペランドの値を返し、それ以外の場合は最初のオペランドの値を返します。

例えば:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy値はにそれらの人強制されているfalseブール値のコンテキストで使用されたとき、彼らは0nullundefined、空の文字列、NaNそしてもちろんfalse


1
+1そのような他のオペレーターはいますか?または||排他的です。
OscarRyz 2010年

9
@Support(@Oscar):論理&&演算子は、同様の振る舞いを持って、それはそれ自体でいた場合、それは最初のオペランドの値を返しfalsyし、最初の1がある場合にのみ、第二オペランドの値を返しますtruthy、例えば("foo" && "bar") == "bar"および(0 && "bar") == 0
CMS

12
ファルシーは実際には専門用語です。
ChaosPandion、2010年

8
そこで、この投稿で||、&&、「Falsy」、「Truly」について学びました。「隠された」ギフトのベストアンサー。
Alex

4
@アレックスNB:「真実」(!「真実」)
バンピー

183

Javacriptは、論理演算子およびに対して短絡評価を使用||&&ます。ただし、truefalse値ではなく、実行を停止した最後の値の結果を返すという点で他の言語とは異なります。

JavaScriptでは、次の値は偽と見なされます。

  • ヌル
  • "" (空の文字列)
  • 0
  • ナン
  • 未定義

演算子の優先順位ルールを無視して、物事を単純に保ち、次の例は、どの値が評価を停止し、結果として返されるかを示しています。

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

最初の5つまでの値NaNは誤りであり、最初の真の値に達するまですべて左から右に評価されます。"Hello"これにより、式全体が真になるため、それ以上の値は評価されず"Hello"、式の結果として返されます。 。同様に、この場合:

1 && [] && {} && true && "World" && null && 2010 // null

最初の5つの値はすべて真実であり、最初の偽の値(null)に達するまで評価されます。これにより、式が偽になり、2010評価されなくなりnull、式の結果として返されます。

あなたが与えた例は、JavaScriptのこのプロパティを使用して割り当てを実行することです。値のセットの中で最初の真または偽の値を取得する必要がある任意の場所で使用できます。このコードは、以下の値が割り当てられます"Hello"b代わりのif-elseチェックを行うので、それはそれが簡単にデフォルト値を割り当てることが可能と。

var a = false;
var b = a || "Hello";

以下の例をこの機能の悪用と呼ぶことができますが、コードが読みにくくなると思います。

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

アラートの内部では、messages誤りがあるかどうかをチェックし、誤りがある場合はnoNewMessagesText評価して戻りnewMessagesTextます。それ以外の場合は評価して戻ります。この例では誤りなので、noNewMessagesTextとalertで停止し"Sorry, you have no new messages."ます。


36
:これは、以下の説明の私の意見では最高の答えですHowever, it's different to other languages in that it returns the result of the last value that halted the execution, instead of a true, or false value.
mastazi

1
@mastaziうん、太字フォントの私見で行く必要があります。
noober

6
答えであるはずです、それはテストケースで選ばれた値を示します。
Dadan 2016

これは特に、JavaScript変数の割り当てに関する問題に対処するため、私のお気に入りの回答です。さらに、代入をテストする後続の変数の1つとして3項を使用することを選択した場合(演算子の後)、割り当ての評価が正しく機能するように、3項を括弧で囲む必要があります。
ジョーイT

これは受け入れられる答えになるはずです
アラン

49

Javascript変数は型指定されていないため、ブール演算子を介して割り当てられている場合でも、fに整数値を割り当てることができます。

fには、falseと等しくない最も近い値が割り当てられます。したがって、0、false、null、undefinedはすべて渡されます。

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'

13
''この場合もfalseに等しいことを忘れないでください。
ブリガンド

f is assigned the NEAREST valueここで非常に重要な点を指摘することに賛成票を投じてください。
steviejay 2016

3
「Nearest」はそのように見えますが、それほど正確ではありません。ブール||左側と右側:ブール演算子である操作者は、2つのオペランドを有します。の左側||trueの場合、操作は左側に解決され、右側は無視されます。左側がである場合、右側に解決されます。だからnull || undefined || 4 || 0実際に解決undefined || 4 || 0する4 || 0解決し4ます。
devios1 2017年

29

魔法はありません。のようなブール式a || b || c || dは遅延評価されます。Interpeterはの値を探しますa。これは未定義なのでfalseなので次に進みます。次にbnullが表示されますが、それでもfalseの結果が出るため、次に進みますc-同じストーリーです。最後にd、「ええ、それはnullではないので、結果が出ました」と表示され、最終的な変数に割り当てられます。

このトリックは、ブール式の遅延短絡評価を行うすべての動的言語で機能します。静的言語ではコンパイルされません(タイプエラー)。ブール式の評価に熱心な言語では、論理値(この場合はtrue)を返します。


6
かなり静的な言語のC#では、?? 演算子ála:オブジェクトf = a ?? b ?? c ?? d ?? e;
ヘルツマイスター、2010年

2
ヘルツマイスター-ありがとう!知らなかった?? 演算子はC#でチェーンされ、遅延評価手法で使用できます
Marek

3
他の場所で述べたように、その最後dは、null /未定義であるかどうかに関係なく割り当てられます。
BlackVegetable 2013

1 ||つのわずかな修正:演算子は、左側が偽である場合、常に右側のオペランド全体に解決します。ブール演算子であるため、左側と右側の2つの入力のみが表示されます。パーサーはそれらを一連の用語として認識しないため、その値が別のの左側のオペランドでもない限り、最初の真の値が見つかったときに実際に停止しません||
devios1 2017年

8

この質問はすでにいくつかの良い答えを受け取っています。

要約すると、この手法は、言語のコンパイル方法の機能を利用しています。つまり、JavaScriptはブール演算子の評価を「短絡」し、最初の偽でない変数値または最後の変数に含まれるものに関連付けられた値を返します。falseと評価されるこれらの値のAnuragの説明を参照してください。

この手法を使用することは、いくつかの理由で良い方法ではありません。しかしながら。

  1. コードの可読性:これはブール演算子を使用しており、このコンパイル方法の動作が理解されていない場合、期待される結果はブール値になります。
  2. 安定性:これは、複数の言語間で一貫性のない言語のコンパイル方法の機能を使用しているため、将来の変更の対象となる可能性があります。
  3. 文書化された機能:このニーズを満たし、より多くの言語で一貫している既存の代替手段があります。これは三項演算子になります:

    ()?値1:値2。

三項演算子を使用するには、もう少しタイプする必要がありますが、評価されるブール式と割り当てられる値を明確に区別します。さらに、それを連鎖させることができるため、上記で実行されているデフォルトの割り当てのタイプを再作成できます。

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f =  ( a ) ? a : 
                ( b ) ? b :
                       ( c ) ? c :
                              ( d ) ? d :
                                      e;

alert(f); // 4

potentially be targeted for change in the future.はい、しかし私はそれがjavascriptには当てはまりません。
Dadan 2016

ここに来て、上記のすべての答えを見て、割り当てについて何かが見落とされているだけだと思っていました。私はちょうどRobert C MartinによるClean Codeを読んでいて、このタイプの割り当ては「副作用がない」規則に間違いなく違反しています...著者自身は彼の本は優れたコードを生成するための多くの手法の1つにすぎないと述べていますが、他の誰もこの種の任務に異議を唱えなかったことにまだ驚きました。+1
Albert Rothman

ご回答ありがとうございます。コードを書くときはもっと多くの人が副作用を考慮する必要があると思いますが、誰かが他の人のコードを維持するのに多くの時間を費やすまでは。彼らはしばしばそれを考慮しません。
WSimpson

1
あなたは本当に怪物がよりはっきりしていると思いますa || b || c || d || eか?
devios1 2017年

1
@AlbertRothman副作用はありません。何も変異していません。これは、null合体の省略形にすぎません。これは、多くの言語で非常に一般的な機能です。
devios1 2017年

7

出力の最初の真の値を返します

すべてがfalseの場合、最後のfalse値を返します。

例:-

  null || undefined || false || 0 || 'apple'  // Return apple

4

新しい変数(z)をx「真実」(ゼロ以外、有効なオブジェクト/配列/関数/それが何であれ)であるか、yそれ以外の値に設定します。これは、デフォルト値を提供する比較的一般的な方法ですxは、存在しない。

たとえば、オプションのコールバックパラメータを取る関数がある場合、何もしないデフォルトのコールバックを提供できます。

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}

1

つまり、xが設定されている場合、の値はにzなりますx。それ以外の場合、yが設定されている場合、その値はzの値ます。

それは同じです

if(x)
  z = x;
else
  z = y;

JavaScriptの論理演算子はブール値を返さないため可能ですが、操作を完了するために必要な最後の要素の値(OR文では最初の非false値、AND文では最後の値になります) )。操作が失敗した場合は、false返されます。


5
これは間違っています!if(x){z = x; } else {z = y;}最初の値がfalseの場合、実際の値に関係なく、2番目の値が常に割り当てられます。
evilpie 2010年

ただし、xがfalseの場合、yをzに割り当てるだけだと思います。それは、FFでの私にとっては当然のことですが、実装に依存する場合もあります。
tvanfosson

7
falseを返す最後の部分はtrueではありません(しゃれは意図されていません)。最初の値が偽の場合、||演算子は真かどうかに関係なく、2番目の値を返します。
Matthew Crumley、2010年

-1。同等のコードスニペットは正確ですが、重要な点は、その値がtrueの場合zにの値に設定されることです。それ以外の場合は、の値に設定されます。つまり、が、または空の文字列などに設定されている場合、これらの値は不正であるため、これはユーザーの言うことを実行しません。xyx0""
ダニエルキャシディ

1

その呼び出された短絡演算子。

短絡評価では、最初の引数が式の値を決定するのに十分でない場合にのみ、2番目の引数が実行または評価されます。OR(||)関数の最初の引数がtrueと評価される場合、全体的な値はtrueでなければなりません。

関数の引数のデフォルト値を設定するためにも使用できます。`

function theSameOldFoo(name){ 
  name = name || 'Bar' ;
  console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`

0

Xを評価し、Xがnull、空の文字列、または0(論理false)でない場合、それをzに割り当てます。Xがnull、空の文字列、または0(論理false)の場合、yをzに割り当てます。

var x = '';
var y = 'bob';
var z = x || y;
alert(z);

'bob'を出力します。


「何もない」という意味を明確にする必要があります。空の文字列はに強制変換されfalseますが、空の配列またはオブジェクトはに強制変換されtrueます。
ダニエルキャシディ

@Daniel "null、empty、or 0"-nullは配列とオブジェクトに適用されます。とはいえ、ポイントを取る。
tvanfosson

0

ビル・ヒギンズのブログ投稿によると、Javascript論理OR割り当てイディオム(2007年2月)、この動作はv1.2以降(少なくとも)

彼はまた、別の使い方(引用)を提案しています:「ブラウザ間の違いを軽量に正規化

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.