構成x = xは何ですか|| どういう意味?


250

JavaScriptをデバッグしていますが、これ||が何をするのか説明できませんか?

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}

誰かが私にヒントを与えることはできますか、なぜこの男は使用していvar title = title || 'ERROR'ますか?私も時々var宣言なしでそれを見ます。


44
人々はすでにこれに答えています...しかし、最初の値がfalsyJUSTではなくの場合、2番目の値が選択されるという事実に非常に注意してundefinedください。私が見た回数doWeDoIt = doWeDoIt || trueは、私を泣かせるのに十分です。(つまり、doWeDoIt今は決してならないfalse
Matt


4
C#の経験がある人にとって、二重パイプ演算子はnull-coalesce演算子と同等??です。Javascriptを評価するnull以外のオブジェクトのような true(またはより良いevalualtesがfalseにオブジェクトをNULL)
USR-ローカルΕΨΗΕΛΩΝ

3
気にしないでください-JSはこの恐ろしいコーディングを可能にする唯一の間抜けな言語です...それと、すべての関数をコード行にネストし、それらを捨てて2回目に使い捨て/使用不可にするのが適切であると教えています。:)私はコーディングに30歳です。少し前まで私自身がJSに触れるのを控えています。私が言えることは、あなたの痛みを感じることです。入手した!:)
Collin Chaffin 2017

1
承認された回答を私の回答に変更することを検討してください。
のMichałPerłakowski

回答:


210

これは、title引数がオプションであることを意味します。したがって、引数なしでメソッドを呼び出すと、デフォルト値のが使用されます"Error"

それは書くための省略形です:

if (!title) {
  title = "Error";
}

ブール式を使用したこの種の略式トリックは、Perlでも一般的です。次の式を使用します。

a OR b

それは評価するtrueかのどちらかabですtrue。したがって、atrueの場合はb、まったくチェックする必要はありません。これは短絡ブール評価と呼ばれるので、

var title = title || "Error";

基本的にがにtitle評価されるかどうかをチェックしfalseます。存在する場合は「戻り」"Error"、それ以外の場合は戻りますtitle



4
これは答えではありません。最後のコメントにも同意します。Perlのステートメントは実際にはSENSEを作成し、完全に異なる方法で評価されるため、この回答のどの部分もPerlのリファレンスでさえ正しくありません。JSは、はるかに「変換された」ブール論理メソッドで評価されているため、読み書きがはるかに混乱しています。以下の「二重パイプ演算子とは」というタイトルの答えは、実際には正しい答えです。
Collin Chaffin 2017

198

二重パイプ演算子(||)とは何ですか?

二重パイプ演算子(||)は論理OR演算子です。でほとんどの言語は、次のように動作します:

  • 最初の値がの場合、false2番目の値をチェックします。の場合trueは戻りtrue、の場合falseはを戻しますfalse
  • 最初の値がの場合、2番目の値が何であっても、true常にを返しますtrue

したがって、基本的には次の関数のように機能します。

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}

それでも理解できない場合は、次の表をご覧ください。

      | true   false  
------+---------------
true  | true   true   
false | true   false  

つまり、両方の値がfalseの場合にのみfalseになります。

JavaScriptの違いは何ですか?

JavaScriptは緩やかに型付けされた言語であるため、少し異なります。この場合、||ブール値ではない値で演算子を使用できることを意味します。意味がありませんが、この演算子を関数やオブジェクトなどで使用できます。

(function(){}) || {}

そこで何が起こりますか?

値がブール値でない場合、JavaScriptは暗黙的にブール値に変換します。これは、値が(例えばfalseyであればということを意味0""nullundefined(も参照のJavaScriptですべてのfalsey値を))、それはとして扱われますfalse。それ以外の場合はとして扱われtrueます。

true空の関数は真実なので、上記の例はを与えるはずです。まあ、そうではありません。空の関数を返します。||最初に書いたようにJavaScriptの演算子が機能しないためです。次のように機能します。

  • 最初の値がfalseの場合、2番目の値を返します
  • 最初の値がである場合、最初の値を返します

驚いた?実際には、従来の||演算子と「互換性があります」。次の関数として書くことができます:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}

真の値をとして渡すと、真の値をx返しxます。したがって、後でif句で使用する場合:

(function(x, y) {
  var eitherXorY = x || y;
  if (eitherXorY) {
    console.log("Either x or y is truthy.");
  } else {
    console.log("Neither x nor y is truthy");
  }
}(true/*, undefined*/));

あなたが得る"Either x or y is truthy."

もしx偽りだったら、eitherXorYだろうy。この場合、あなたは"Either x or y is truthy."if yが真実であることを得るでしょう。そうでなければあなたは得るでしょう"Neither x nor y is truthy"

実際の質問

さて、||演算子がどのように機能するかを知っていれば、おそらく自分で何がx = x || y意味するのかを理解できます。xが真実の場合、xに割り当てられるためx、実際には何も起こりません。それ以外の場合yはに割り当てられxます。これは通常、関数のデフォルトパラメータを定義するために使用されます。しかし、しばしば考えられている悪いプログラミングの練習、それはfalsey値を渡してからあなたを防ぐため、(必ずしもされていない、undefinedまたはnullパラメータとして)。次の例を検討してください。

function badFunction(/* boolean */flagA) {
  flagA = flagA || true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

一見有効に見えます。ただし、パラメーターfalseとして渡した場合はどうなりますかflagA(ブール値であるため、trueまたはにすることができますfalse)?なるでしょうtrueこの例では、に設定flagAする方法はありませんfalse

明示的かどうかを確認するために良いアイデアだろうflagAであるundefinedことのように、:

function goodFunction(/* boolean */flagA) {
  flagA = typeof flagA !== "undefined" ? flagA : true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

長いですが、常に機能し、理解しやすくなっています。


ES6構文をデフォルトの関数パラメーターに使用することもできますが、それは古いブラウザー(IEなど)では機能しないことに注意してください。これらのブラウザーをサポートする場合は、コードをBabelでトランスパイルする必要があります。

MDNの論理演算子も参照してください。


13
+1-はるかに正確で完全な答え。そして、この質問のある人(JSに慣れていないベテランプログラマーの何人か)は、この行全体でこの答え全体の中で最も焦点を当てる必要があります:「それは意味がありません」。それなしで育った私たちに。私たちにとって、ブール演算子はまさにそれだけです......そしてコードを読み書きしているときにブール値以外のブール値への奇妙な変換を止めて考える必要があると考えた人は誰でもいます、その日に薬を服用するのを忘れた!:)
Collin Chaffin 2017

2
+1、簡単に言えば:title = title || 'Error'意味if (title) { title = title; } else { title = 'Error'; }
Andre Elrico

「意味がありませんが」という言葉には実際には同意しません。たとえば、行がCでコンパイルされないことは理解していますが、たとえばRubyやGroovyから来た場合はよく理解されています。Rubyでは、さらに短く表現できますtitle ||= 'Error'
Elliot Nelson

28

タイトルが設定されていない場合、デフォルト値として「ERROR」を使用します。

より一般的な:

var foobar = foo || default;

読み取り:foobarをfooまたはに設定しdefaultます。これを何度も連鎖させることもできます。

var foobar = foo || bar || something || 42;

1
変数の名前が同じであるため、混乱を招きました。そうでない場合ははるかに簡単です。
Norbert Norbertson 2017年

14

これについてもう少し説明...

||オペレータはlogical-あるor演算子。最初の部分がtrueの場合、結果はtrueになり、2番目の部分がtrueの場合はtrue、両方の部分がtrueの場合はtrueになります。わかりやすくするために、ここに表を示します。

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

ここで何か気づきましたか?場合はXtrueで、結果は常に真です。したがって、それXが本当であることがわかっている場合はY、まったくチェックする必要はありません。したがって、多くの言語は、論理or(および論理- and他の方向から来る)の「短絡」エバリュエーターを実装します。彼らは最初の要素をチェックし、それが真である場合、2番目の要素をまったくチェックしません。結果(論理的に)は同じですが、2番目の要素の計算にコストがかかる場合、実行に関して大きな違いが生じる可能性があります。

それで、これはあなたの例と何が関係していますか?

var title   = title || 'Error';

それを見てみましょう。title要素はあなたの関数に渡されます。JavaScriptでは、パラメーターを渡さない場合、デフォルトでnull値になります。また、JavaScriptでは、変数がnull値の場合、論理演算子によってfalseと見なされます。したがって、この関数が与えられたタイトルで呼び出された場合、それは偽ではない値であり、ローカル変数に割り当てられます。ただし、値が指定されていない場合はnull値であるため、falseになります。次に、論理or演算子は2番目の式を評価し、代わりに「エラー」を返します。したがって、ローカル変数には値「Error」が与えられます。

これは、JavaScriptに論理式が実装されているために機能します。これは適切なブール値(trueまたはfalse)を返しませんが、同等と見なされるものtrueおよび同等と見なされるものに関していくつかのルールの下で指定された値を返しますfalse。JavaScriptリファレンスを調べて、JavaScriptがブールコンテキストでtrueまたはfalseと見なすものを確認します。


8

二重パイプは論理「OR」を表します。これは、「パラメータが設定されていない」場合には実際には当てはまりません。厳密には、次のようなコードがある場合、JavaScriptに含まれるためです。

function foo(par) {
}

次に電話します

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

同等ではありません。

二重パイプ(||)は、最初の引数をブール値にキャストし、結果のブール値がtrueの場合-割り当てを実行します。それ以外の場合は、正しい部分を割り当てます。

これは、未設定のパラメーターをチェックする場合に重要です。

たとえば、オプションのパラメーターが1つある関数setSalaryがあるとします。ユーザーがパラメーターを指定しない場合は、デフォルト値の10を使用する必要があります。

次のようにチェックすると:

function setSalary(dollars) {
    salary = dollars || 10
}

これは次のような呼び出しで予期しない結果をもたらします

setSalary(0) 

上記のフローに従って、引き続き10が設定されます。


8

基本的に、||の前の値が trueと評価し、yesの場合はこの値を取得し、そうでない場合は、||の後に値を取得します。

||の後の値を取る値 (覚えてる限り):

  • 未定義
  • 0
  • ''(NullまたはNull文字列)

1
誤り|| null || 未定義|| 0 || 」|| 「nullを忘れた」
Dziamid

7

一方でCletus'答えは正しいですが、私は詳しくはJavaScriptで『falseと評価』に関してで追加する必要があります感じています。

var title = title || 'Error';
var msg   = msg || 'Error on Request';

タイトル/メッセージが提供されているかどうかを確認するだけでなく、どちらかが不正であるかどうかも確認します。つまり、次のいずれかです。

  • 偽。
  • 0(ゼロ)
  • ""(空の文字列)
  • ヌル。
  • 未定義。
  • NaN(Not-a-Numberを意味する特別なNumber値!)

だから行で

var title = title || 'Error';

タイトルが真実である(つまり、偽物ではないため、title = "titleMessage"など)場合、ブールOR(||)演算子は1つの「true」値を検出しました。つまり、trueと評価され、短絡して返されます真の値(タイトル)。

タイトルが偽の場合(つまり、上記のリストの1つ)、ブールOR(||)演算子は 'false'値を検出し、演算子の他の部分である 'Error'を評価する必要があります。 、したがって返されます。

また、(いくつかのFirebugコンソールの実験の後)演算子の両側がfalseと評価された場合、2番目の「偽の」演算子を返します。

すなわち

return ("" || undefined)

未定義を返します。これはおそらく、デフォルトのタイトル/メッセージを「」にしようとするときに、この質問で尋ねられた動作を使用できるようにするためです。すなわち実行した後

var foo = undefined
foo = foo || ""

fooは ""に設定されます


5

二重パイプ演算子

この例は役に立ちますか?

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

することもできます

var section = document.getElementById('special') || document.getElementById('main');

4

私の前に言ったすべてにいくつかの説明を追加するために、論理的な概念を理解するためにいくつかの例を挙げましょう。

var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true

これは、左側が真のステートメントとして評価された場合、終了し、左側が返されて変数に割り当てられることを意味します。それ以外の場合は、右側が返されて割り当てられます。

そして、演算子は以下のような反対の構造を持っています。

var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh

3

|| ブールOR演算子です。javascriptの場合と同様に、undefined、null、0、falseは、 falsy値。

それは単に意味します

true || true = true
false || true = true
true || false = true
false || false = false

undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"

2

引用:「構成x = x || yはどういう意味ですか?」

デフォルト値を割り当てます。

これは、xがxにデフォルト値を提供することを意味します。xはまだその値を待っているが、まだそれを受け取っていないか、デフォルトにフォールバックするために意図的に省略された場合です。


それが構造の正確な意味であり、それの唯一の意味です。そしてそれは、プロトタイプ、スタンドアロン関数として、そして他の要素に適用するために借りたメソッドとしてフェッチできる関数を書く際のサブルーチンとして大いにありました。その主かつ唯一の義務は、ターゲットの参照を変更することでした。例:function getKeys(x) { x = x || this ; .... }スタンドアロン関数として、プロトタイプのプロパティメソッドとして、および `[element] .getKeys(anotherElement);`として別の要素を引数として取得できる要素のメソッドとして、そのまま使用できます
Bekim Bacaj

-5

そして、もう1つ追加する必要があります。この省略形は嫌悪感です。偶発的なインタープリター最適化を誤用し(最初の操作が真実である場合は2番目の操作を邪魔しない)、割り当てを制御します。その使用は、オペレーターの目的とは関係ありません。私はそれが今まで使われるべきだとは思いません。

私は初期化のために三項演算子を好む、例えば

var title = title?title:'Error';

これは、正しい目的のために1行の条件付き演算を使用します。それはまだ真実で見苦しいゲームをしますが、それはあなたのためのJavascriptです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.