回答:
JavaScriptは祖先をCまで追跡し、Cには論理XOR演算子がありません。主にそれが役に立たないからです。ビットワイズXORは非常に便利ですが、これまでのプログラミングでは論理XORは必要ありませんでした。
2つのブール変数がある場合は、次のようにしてXORを模倣できます。
if (a != b)
2つの任意の変数を使用!
すると、ブール値に強制的に変換してから同じトリックを使用できます。
if (!a != !b)
それはかなりあいまいで、確かにコメントに値するでしょう。確かに、この時点ではビット単位のXOR演算子を使用することもできますが、これは私の好みにはあまりにも賢いでしょう。
if (!a ^ !b)
Javascriptにはビット単位のXOR演算子があります:^
var nb = 5^9 // = 12
ブール値と一緒に使用すると、結果は0または1になります(ブール値に変換できますresult = !!(op1 ^ op2)
)。しかし、Johnが言ったようにresult = (op1 != op2)
、これはと同等です。
true^true
0で、かつfalse^true
1です
||
また&&
、非ブール値の論理演算子として使用できます(たとえば5 || 7
、真の値を"bob" && null
返し、偽の値を返します)が^
できません。たとえば、5 ^ 7
2は真です。
(true ^ false) !== true
実際のブール値を必要とするライブラリでは煩わしい
a ^= true
ブール値を切り替えるために使用していたが、電話などの一部のマシンでは失敗する。
Javascriptには実際の論理ブール演算子はありません(!
かなり接近していますが)。論理演算子はかかるだろうtrue
か、false
オペランドとしてのみ返すでしょうtrue
かfalse
。
JavaScript &&
および||
あらゆる種類のオペランド取り、あらゆる種類の面白い結果を返します(それらに入力したものは何でも)。
また、論理演算子は常に両方のオペランドの値を考慮する必要があります。
JavaScriptで&&
と||
怠惰なショートカットを取り、んではない特定の場合には第二オペランドを評価し、それによって、その副作用を無視。この動作は、論理XORで再作成することは不可能です。
a() && b()
a()
偽の場合、結果を評価して返します。それ以外の場合b()
は、結果を評価して返します。したがって、返される結果は、両方の結果が真である場合は真であり、そうでない場合は偽です。
a() || b()
a()
真実であれば結果を評価して返します。それ以外の場合b()
は、結果を評価して返します。したがって、両方の結果が偽である場合、返される結果は偽であり、それ以外の場合は真実です。
したがって、一般的な考え方は、最初に左のオペランドを評価することです。右側のオペランドは、必要な場合にのみ評価されます。そして最後の値は結果です。この結果は何でもかまいません。オブジェクト、数字、文字列..なんでも!
これにより、次のような記述が可能になります。
image = image || new Image(); // default to a new Image
または
src = image && image.src; // only read out src if we have an image
ただし、この結果の真理値は、「実際の」論理演算子がtrueまたはfalseを返すかどうかを決定するためにも使用できます。
これにより、次のような記述が可能になります。
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
または
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
ただし、「論理」xor演算子(^^
)は常に両方のオペランドを評価する必要があります。これにより、必要な場合にのみ2番目のオペランドを評価する他の「論理」演算子とは異なります。これが、混乱を避けるために、Javascriptに「論理的な」XORがない理由だと思います。
では、両方のオペランドが偽である場合はどうなりますか?両方とも返される可能性があります。ただし、返却できるのは1つだけです。どれ?最初の1つ?それとも2つ目?私の直感は、最初の、しかし通常「論理的な」演算子は左から右に評価し、最後に評価された値を返すように指示しています。または、両方の値を含む配列ですか?
そして、一方のオペランドが真であり、もう一方のオペランドが偽である場合、xorは真のオペランドを返す必要があります。それとも、前のケースと互換性を持たせるために、真実な配列を含む配列を使用しますか?
そして最後に、両方のオペランドが真実である場合はどうなりますか?あなたは何かおかしいと期待するでしょう。しかし、偽の結果はありません。したがって、操作は何も返しません。だから多分undefined
または..空の配列?しかし、空の配列はまだ真実です。
配列アプローチをとると、次のような状態になりif ((a ^^ b).length !== 1) {
ます。とても紛らわしい。
ある...のようなもの:
if( foo ? !bar : bar ) {
...
}
または読みやすい:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
どうして?知らない。
javascript開発者は、すでに実装されている他の論理演算子で表現できるので、それは不要だと思ったからです。
nandでgonを使用することもできます。これで、他のすべての可能な論理演算を印象付けることができます。
私は個人的に、Cベースの構文言語からの歴史的な理由があると思います。私の知る限りでは、xorが存在しないか、少なくとも非常に珍しいものです。
はい、次のようにしてください。ブールAとBを扱っているとすると、A XOR B値はJavaScriptで次のように計算できます。
var xor1 = !(a === b);
前の行も次と同等です
var xor2 = (!a !== !b);
個人的には、入力する文字数を減らす必要があるため、xor1を好みます。xor1も高速だと思います。2つの計算を実行するだけです。xor2は3つの計算を実行しています。
視覚的な説明...以下の表を読んで(0はfalseを表し、1はtrueを表します)、3列目と5列目を比較します。
!(A === B):
| A | B | A XOR B | A === B | !(A === B) |
------------------------------------------
| 0 | 0 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 1 | 0 |
------------------------------------------
楽しい。
var xor1 = !(a === b);
と同じですvar xor1 = a !== b;
!(2 === 3)
ですtrue
が、2
と3
あるtruthyそう2 XOR 3
でなければなりませんfalse
。
結果のintを二重否定のboolに変換してみませんか?それほどきれいではありませんが、本当にコンパクトです。
var state1 = false,
state2 = true;
var A = state1 ^ state2; // will become 1
var B = !!(state1 ^ state2); // will become true
console.log(A);
console.log(B);
B = ((!state1)!==(!state2))
B =!!(!state1 ^ !state2);
また、括弧が多いのはなぜですか。B = !state1 !== !state2;
それともあなたも否定をドロップすることができます:B = state1 !== state2;
state1 !== state2
そこでキャストする必要はありません!==
。12 !== 4
本当'xy' !== true
ですまた本当です の!=
代わりに使用する場合は!==
、キャストを行う必要があります。
!==
とは!=
常にブール...あなたが作っているの区別は絶対的に問題ではないこと、があることが想定されていないことを確認するものです。問題は、我々はXOR演算子であることを望むが、本当に表現です(Boolean(state1) !== Boolean(state2))
。ブール値の場合、「xy」、true
12、4 およびはすべて真の値であり、に変換する必要がありtrue
ます。そうする("xy" XOR true)
必要がありますがfalse
、あなたが指摘するように("xy" !== true)
代わりtrue
にです。つまり!==
、適用する前に引数をブール値に変換した場合に限り、!=
(どちらも)「論理XOR」と同等になります。
上記のxor関数では、論理xorが厳密に論理xorではないため、類似した結果になります。つまり、データ型の一致を考慮して、「等しい値の場合はfalse」、「異なる値の場合はtrue 」になります。
このXOR関数は、実際のXORまたは論理演算子として動作します、それは渡す値にtrueまたはfalse応じてつながる手段があり、truthyまたはfalsy。ニーズに合わせてご利用ください
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
(!!x) === (!!y)
です。違いはブール値へのキャストです。'' === 0
は偽であり、xnor('', 0)
真は真です。
Typescript(+は数値に変わります):
value : number = (+false ^ +true)
そう:
value : boolean = (+false ^ +true) == 1
!!(false ^ true)
ブール値で正常に機能します。typescriptでは、有効にするために+が必要です!!(+false ^ +true)
。
論理XOR(^^)がない理由は、&&および||とは異なります。遅延論理的な利点はありません。それが評価されなければならない右と左の両方の式の状態です。
2つ以上の変数で機能し、ボーナスとしてカウントを提供する代替ソリューションを次に示します。
標準のIFステートメントに演算子があるかのように、真偽値の論理XORをシミュレートするためのより一般的なソリューションを次に示します。
const v1 = true;
const v2 = -1; // truthy (warning, as always)
const v3 = ""; // falsy
const v4 = 783; // truthy
const v5 = false;
if( ( !!v1 + !!v2 + !!v3 + !!v4 + !!v5 ) === 1 )
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is TRUE!` );
else
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is FALSE!` );
私がこれを好きな理由は、「これらの変数のうちいくつが真実であるか」にも答えるため、通常はその結果を事前に保存します。
そして、厳密なブール値-TRUEのxorチェック動作を必要とする人は、次のようにします。
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.
カウントを気にしない場合、または最適なパフォーマンスを気にする場合:真偽のソリューションでは、ブール値に強制変換された値にビット単位のxorを使用します。
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.
これを短く理解しやすいものにしてください
function xor(x,y){return true==(x!==y);}
function xnor(x,y){return !xor(x,y);}
これはどのデータ型でも機能します
true == someboolean
必要はないので、実際には、厳密に等しくないものを関数にラップしています。
!=
、と同じことを実行できないことです。a ^= b
a !== b