JavaScript に論理 xor がないのはなぜですか?
19 に答える
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))。result = (op1 != op2)しかし、ジョンが言ったように、それはより明確な と同等です。
Javascript には実際の論理ブール演算子はありません (ただし、!非常に近くなっています)。論理演算子は or のみをオペランドとして取りtrue、 orfalseのみを返しtrueますfalse。
Javascript では、すべての種類のオペランド&&を||取り、すべての種類の面白い結果を返します (それらに入力したものは何でも)。
また、論理演算子は常に両方のオペランドの値を考慮に入れる必要があります。
Javascript では&&、||怠惰なショートカットを使用して、特定のケースで 2 番目のオペランドを評価しないため、その副作用を無視できます。この動作は、論理 xor で再現することはできません。
a() && b()偽の場合は結果を評価a()して返します。それ以外の場合は、評価b()して結果を返します。したがって、両方の結果が true の場合、返される結果は true であり、そうでない場合は false です。
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 は真のオペランドを返す必要があります。または、前のケースと互換性を持たせるために、真実のものを含む配列でしょうか?
最後に、両方のオペランドが true の場合はどうなるでしょうか? あなたは何か偽物を期待するでしょう。しかし、偽の結果はありません。したがって、操作は何も返すべきではありません。たぶんundefined、または..空の配列ですか?しかし、空の配列は依然として真実です。
配列アプローチを取ると、次のような条件になりif ((a ^^ b).length !== 1) {ます。非常に紛らわしいです。
2 つのブール値の XOR は、単純にそれらが異なるかどうかです。したがって、次のようになります。
Boolean(a) !== Boolean(b)
ある...一種の:
if( foo ? !bar : bar ) {
...
}
または読みやすい:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
なぜ?わからない。
JavaScript 開発者は、すでに実装されている他の論理演算子で表現できるため、不要だと考えていたためです。
nand を使用することもできます。それだけで、他のすべての可能な論理演算に感銘を与えることができます。
個人的には、xor が存在しないか、少なくとも非常に珍しい c ベースの構文言語から派生した歴史的な理由があると思います。
はい、次のことを行ってください。ブール値 A と B を扱っていると仮定すると、JavaScript で次を使用して A XOR B 値を計算できます。
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 |
------------------------------------------
楽しみ。
ブール値の 1 つのライナー:
if (x ? !y : y) { do something cool }
上記の xor 関数では、論理 xor は厳密には論理 xor ではないため、SIMILARの結果になります。つまり、データ型の一致を考慮して、「等しい値の場合は false」、「異なる値の場合は true 」になります。
この xor 関数は、実際の xor または論理演算子として機能します。つまり、渡される値がtrueまたはfalseであることに応じて、結果が true または false になります。用途に合わせてご利用ください
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
論理的 XOR (^^) がない理由は、&& や || とは異なるためです。遅延論理の利点はありません。つまり、左右両方の式を評価する必要がある状態です。