web-dev-qa-db-ja.com

JavaScriptに論理XORがないのはなぜですか?

JavaScriptに論理XORがないのはなぜですか?

177
DarkLightA

JavaScriptはその祖先をCにトレースし、Cには論理XOR演算子がありません。主にそれが役に立たないからです。ビット単位のXORは非常に便利ですが、長年のプログラミングのすべてで論理XORは必要ありませんでした。

2つのブール変数がある場合、XORを模倣できます:

if (a != b)

2つの任意の変数を使用すると、!を使用してそれらをブール値に強制し、同じトリックを使用できます。

if (!a != !b)

しかし、それはかなりあいまいであり、確かにコメントに値するでしょう。実際、この時点でビット単位のXOR演算子を使用することもできますが、これは私の好みにはあまりにも賢いでしょう:

if (!a ^ !b)
339
John Kugelman

Javascriptにはビット単位のXOR演算子があります:^

var nb = 5^9 // = 12

ブール値で使用でき、結果を0または1として返します(ブール値に変換して戻すことができます(例:result = !!(op1 ^ op2)))。しかし、ジョンが言ったように、それはresult = (op1 != op2)と同等です。

75
Pikrass

Javascriptには実際の論理ブール演算子はありません(!は非常に近くなります)。論理演算子は、オペランドとしてtrueまたはfalseのみを取り、trueまたはfalseのみを返します。

Javascriptでは、&&および||は、あらゆる種類のオペランドを取り、あらゆる種類の面白い結果(それらにフィードするものは何でも)を返します。

また、論理演算子は常に両方のオペランドの値を考慮する必要があります。

Javascriptで&&および||は、怠shortcutなショートカットを取り、特定の場合にnot 2番目のオペランドを評価し、その副作用を無視します。この動作を論理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) {のような状態になります。非常に紛らわしいです。

28
Robert

2つのブール値のXORは、単にそれらが異なるかどうかです。したがって、

Boolean(a) !== Boolean(b)
11
DomQ

ある...種類の:

if( foo ? !bar : bar ) {
  ...
}

または読みやすい:

if( ( foo && !bar ) || ( !foo && bar ) ) {
  ...
}

どうして?知らない。

javascript開発者は、すでに実装されている他の論理演算子で表現できるため、不要だと考えたためです。

同様に、nandを持つgonを持つこともできます。それから、他のすべての可能な論理演算を印象付けることができます。

個人的には、xorが存在しないか、少なくとも非常に珍しい、cベースの構文言語から派生した歴史的な理由があると思います。

9
The Surrican

はい、次の操作を行ってください。ブール値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     |
------------------------------------------

楽しい。

7
asiby

Booleanに変換してから、次のようにxorを実行します-

!!a ^ !!b
6
toyeca

値をブール形式に変換し、ビット単位のXORを取ります。非ブール値にも役立ちます。

Boolean(a) ^ Boolean(b)
5
Aman Kaushal

チェックアウト:

次のように模倣できます。

if( ( foo && !bar ) || ( !foo && bar ) ) {
  ...
}
4
Sarfraz

結果を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);
4
Lajos Meszaros

上記のxor関数では、論理xorが正確に論理xorではないため、結果はSIMILARとなり、結果は"false for equal values"および"異なる値に対してtrue "データ型の一致を考慮します。

このxor関数実際のxorまたは論理演算子として機能しますは、渡す値に応じてtrueまたはfalseになることを意味しますtruthyまたはfalsy。ニーズに合わせて使用

function xor(x,y){return true==(!!x!==!!y);}

function xnor(x,y){return !xor(x,y);}
2

cond1 xor cond2cond1 + cond 2 == 1と同等であるという事実を使用します。

let ops = [[false, false],[false, true], [true, false], [true, true]];

function xor(cond1, cond2){
  return cond1 + cond2 == 1;
}

for(op of ops){
  console.log(`${op[0]} xor ${op[1]} is ${xor(op[0], op[1])}`)
}
1
madjaoue

TypeScriptの場合(+は数値に変わります):

value : number = (+false ^ +true)

そう:

value : boolean = (+false ^ +true) == 1
0
Witold Kaczurba

論理XOR(^^)がない理由は、&&や||とは異なるためです。レイジーロジックの利点はありません。これは、右側と左側の両方の式の状態を評価する必要があることです。

0
user7163886