JavaScript에 논리적 xor가없는 이유는 무엇입니까?
JavaScript에 논리적 xor가없는 이유는 무엇입니까?
답변:
JavaScript는 조상을 다시 C로 추적하며 C에는 논리적 XOR 연산자가 없습니다. 주로 유용하지 않기 때문에. Bitwise XOR은 매우 유용하지만 수년간의 프로그래밍에서 논리적 XOR이 필요하지 않았습니다.
부울 변수가 두 개인 경우 다음을 사용하여 XOR을 모방 할 수 있습니다.
if (a != b)
두 개의 임의 변수를 사용하면 변수 !
를 부울 값으로 강제 변환하고 동일한 트릭을 사용할 수 있습니다.
if (!a != !b)
그래도 꽤 모호하며 분명히 의견이 필요합니다. 실제로이 시점에서 비트 XOR 연산자를 사용할 수도 있지만 내 취향에는 너무 영리합니다.
if (!a ^ !b)
자바 스크립트에는 비트 XOR 연산자가 있습니다 : ^
var nb = 5^9 // = 12
부울과 함께 사용할 수 있으며 결과를 0 또는 1로 제공합니다 (예를 들어 부울로 다시 변환 할 수 있음 result = !!(op1 ^ op2)
). 그러나 John이 말했듯이 result = (op1 != op2)
이는보다 명확합니다.
true^true
0, false^true
1입니다.
||
및 &&
비 논리 값에 논리 연산자로 사용 (예 : 수 5 || 7
하는 truthy 값을 반환 "bob" && null
falsey 값을 반환)하지만 ^
할 수 없습니다. 예를 들어, 5 ^ 7
2는 진실입니다.
(true ^ false) !== true
실제 부울을 필요로하는 라이브러리를 사용하면 성
a ^= true
부울을 전환하기 위해 일종의를 사용하고 있었고 전화와 같은 일부 컴퓨터에서는 실패합니다.
Javascript에는 실제 논리 부울 연산자가 없습니다 ( !
아주 가깝습니다). 논리 연산자는 걸릴 것 true
또는 false
피연산자 만 반환 true
또는 false
.
자바 스크립트 &&
와 ||
피연산자의 모든 종류를 가지고 (당신이 그들로 공급 무엇이든) 재미 결과의 모든 종류를 반환합니다.
또한 논리 연산자는 항상 두 피연산자의 값을 고려해야합니다.
자바 스크립트 &&
와 ||
게으른 바로 가기를 가지고 할 수 없습니다 어떤 경우함으로써 부작용 방치 두 번째 피연산자를 평가합니다. 이 동작은 논리 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 연산자 ( ^^
)는 항상 두 피연산자를 모두 평가해야합니다. 이것은 필요한 경우에만 두 번째 피연산자를 평가하는 다른 "논리적"연산자와는 다릅니다. 혼동을 피하기 위해 이것이 자바 스크립트에 "논리적"xor가없는 이유라고 생각합니다.
두 피연산자가 모두 잘못된 경우 어떻게됩니까? 둘 다 반환 될 수 있습니다. 그러나 하나만 반환 할 수 있습니다. 어느 것? 첫번째? 아니면 두 번째? 내 직감은 첫 번째이지만 일반적으로 "논리적"연산자는 왼쪽에서 오른쪽으로 평가하고 마지막으로 평가 된 값을 반환하도록 지시합니다. 아니면 두 값을 모두 포함하는 배열입니까?
그리고 한 피연산자가 진실이고 다른 피연산자가 거짓이면, xor는 진실한 피연산자를 반환해야합니다. 아니면 이전 사례와 호환되도록 진실한 배열을 포함하는 배열입니까?
마지막으로 두 피연산자가 모두 진실이라면 어떻게됩니까? 당신은 뭔가 잘못된 것을 기대할 것입니다. 그러나 허위 결과는 없습니다. 따라서 작업이 아무것도 반환해서는 안됩니다. 아마도 undefined
또는 .. 빈 배열입니까? 그러나 빈 배열은 여전히 진실입니다.
배열 접근 방식을 사용하면 다음과 같은 조건으로 끝납니다 if ((a ^^ b).length !== 1) {
. 매우 혼란 스럽습니다.
... 종류가 있습니다 :
if( foo ? !bar : bar ) {
...
}
또는 더 읽기 쉽다 :
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
왜? 던노
자바 스크립트 개발자는 이미 구현 된 다른 논리 연산자로 표현할 수 있으므로 불필요하다고 생각했기 때문입니다.
당신은 낸드와 곤두박질을 할 수 있으며, 그로부터 가능한 모든 다른 논리 연산에 깊은 인상을 줄 수 있습니다.
개인적으로 c 기반 구문 언어를 사용하는 역사적인 이유가 있다고 생각합니다. 제 지식이 없거나 적어도 매우 드문 곳입니다.
예, 다음을 수행하십시오. 부울 A 및 B를 처리한다고 가정하면 다음을 사용하여 JavaScript에서 A XOR B 값을 계산할 수 있습니다
var xor1 = !(a === b);
이전 줄은 다음과 같습니다.
var xor2 = (!a !== !b);
개인적으로 문자를 적게 입력해야하기 때문에 xor1을 선호합니다. xor1도 더 빠르다고 생각합니다. 두 가지 계산을 수행하고 있습니다. xor2는 세 가지 계산을 수행합니다.
시각적 설명 ... 다음 표 (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 를 이중 부정 으로 부울 로 변환하는 것은 어떻습니까? 그렇게 예쁘지는 않지만 실제로는 컴팩트합니다.
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", 12, 4이며 true
모두 진솔한 값이며로 변환해야합니다 true
. 당신이 지적한대로 그렇게 ("xy" XOR true)
해야 false
하지만 ("xy" !== true)
대신 true
에 있습니다. 그래서 !==
나 !=
있다 "논리적 인 XOR"을 (모두) 해당하는 경우에만, 당신이 논리 값에 해당 인수를 변환 하기 전에 적용.
위의 xor 함수 에서 논리 xor는 정확히 논리 xor가 아니기 때문에 SIMILAR 결과가 나옵니다. 즉, 데이터 유형 일치를 고려하여 " 동일한 값에 대해서는 거짓" 및 "다른 값에 대해서는 참" 을 의미합니다.
이 XOR 기능은 실제 또는 XOR 논리 연산자로 작동 , 통과 값은하기가 참 또는 거짓 결과있어서 의미 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)
입니다.
다음은 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