Câu trả lời:
JavaScript truy nguyên tổ tiên của nó trở lại C và C không có toán tử XOR logic. Chủ yếu là vì nó không hữu ích. Bitwise XOR cực kỳ hữu ích, nhưng trong tất cả các năm lập trình, tôi chưa bao giờ cần một XOR logic.
Nếu bạn có hai biến boolean, bạn có thể bắt chước XOR với:
if (a != b)
Với hai biến tùy ý, bạn có thể sử dụng !
để ép buộc chúng thành các giá trị boolean và sau đó sử dụng cùng một mẹo:
if (!a != !b)
Điều đó khá mơ hồ và chắc chắn sẽ xứng đáng nhận xét. Thật vậy, bạn thậm chí có thể sử dụng toán tử XOR bitwise vào thời điểm này, mặc dù điều này sẽ quá thông minh đối với sở thích của tôi:
if (!a ^ !b)
Javascript có toán tử XOR bitwise: ^
var nb = 5^9 // = 12
Bạn có thể sử dụng nó với booleans và nó sẽ cho kết quả là 0 hoặc 1 (mà bạn có thể chuyển đổi trở lại thành boolean, ví dụ result = !!(op1 ^ op2)
). Nhưng như John nói, nó tương đương với result = (op1 != op2)
, điều này rõ ràng hơn.
true^true
là 0 và false^true
là 1.
||
và &&
có thể được sử dụng như các toán tử logic trên các giá trị không phải 5 || 7
là booleans (ví dụ trả về giá trị trung thực, "bob" && null
trả về giá trị falsey) nhưng ^
không thể. Ví dụ, 5 ^ 7
bằng 2, đó là sự thật.
(true ^ false) !== true
điều này gây khó chịu với các thư viện yêu cầu
a ^= true
để chuyển đổi booleans và nó đã thất bại trên một số máy như điện thoại.
Không có toán tử boolean logic thực sự trong Javascript (mặc dù !
khá gần). Một toán tử logic sẽ chỉ lấy true
hoặc false
làm toán hạng và sẽ chỉ trả về true
hoặcfalse
.
Trong Javascript &&
và||
lấy tất cả các loại toán hạng và trả về tất cả các loại kết quả hài hước (bất cứ điều gì bạn đưa vào chúng).
Ngoài ra, một toán tử logic phải luôn luôn tính đến các giá trị của cả hai toán hạng.
Trong Javascript &&
và ||
thực hiện một phím tắt lười biếng và không đánh giá toán hạng thứ hai trong một số trường hợp nhất định và do đó bỏ qua các tác dụng phụ của nó. Hành vi này là không thể để tạo lại với một xor logic.
a() && b()
đánh giá a()
và trả về kết quả nếu nó sai. Nếu không thì nó đánh giáb()
và trả về kết quả. Do đó, kết quả trả về là trung thực nếu cả hai kết quả là trung thực và sai.
a() || b()
đánh giá a()
và trả về kết quả nếu nó là sự thật. Nếu không thì nó đánh giáb()
và trả về kết quả. Do đó, kết quả trả về là sai lệch nếu cả hai kết quả đều sai lệch và ngược lại.
Vì vậy, ý tưởng chung là đánh giá toán hạng bên trái trước. Toán hạng bên phải chỉ được đánh giá nếu cần thiết. Và giá trị cuối cùng là kết quả. Kết quả này có thể là bất cứ điều gì. Đối tượng, số, chuỗi .. bất cứ điều gì!
Điều này làm cho nó có thể viết những thứ như
image = image || new Image(); // default to a new Image
hoặc là
src = image && image.src; // only read out src if we have an image
Nhưng giá trị thật của kết quả này cũng có thể được sử dụng để quyết định xem một toán tử logic "thực" sẽ trả về đúng hay sai.
Điều này làm cho nó có thể viết những thứ như
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
hoặc là
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
Nhưng một toán tử xor "logic" ( ^^
) sẽ luôn phải đánh giá cả hai toán hạng. Điều này làm cho nó khác với các toán tử "logic" khác chỉ đánh giá toán hạng thứ hai nếu cần thiết. Tôi nghĩ đây là lý do tại sao không có xor "logic" trong Javascript, để tránh nhầm lẫn.
Vì vậy, những gì sẽ xảy ra nếu cả hai toán hạng là giả? Cả hai có thể được trả lại. Nhưng chỉ có một có thể được trả lại. Cái nào? Cái đầu tiên? Hay cái thứ hai? Trực giác của tôi bảo tôi trả về các toán tử đầu tiên nhưng thường "logic" đánh giá từ trái sang phải và trả về giá trị được đánh giá cuối cùng. Hoặc có thể một mảng chứa cả hai giá trị?
Và nếu một toán hạng là trung thực và toán hạng khác là sai, một xor sẽ trả về giá trị trung thực. Hoặc có thể là một mảng chứa một sự thật, để làm cho nó tương thích với trường hợp trước?
Và cuối cùng, điều gì sẽ xảy ra nếu cả hai toán hạng là sự thật? Bạn sẽ mong đợi một cái gì đó giả. Nhưng không có kết quả giả. Vì vậy, các hoạt động không nên trả lại bất cứ điều gì. Vì vậy, có thể undefined
hoặc .. một mảng trống? Nhưng một mảng trống vẫn là sự thật.
Theo cách tiếp cận mảng, bạn sẽ kết thúc với các điều kiện như if ((a ^^ b).length !== 1) {
. Rất bối rối.
Chuyển đổi giá trị thành dạng Boolean sau đó lấy XOR bitwise. Nó sẽ giúp với các giá trị không boolean là tốt.
Boolean(a) ^ Boolean(b)
có ... loại:
if( foo ? !bar : bar ) {
...
}
hoặc dễ đọc hơn:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
tại sao? không biết.
bởi vì các nhà phát triển javascript nghĩ rằng nó sẽ không cần thiết vì nó có thể được thể hiện bởi các toán tử logic khác, đã được triển khai.
bạn cũng có thể có gon với nand và đó là nó, bạn có thể gây ấn tượng với mọi hoạt động logic có thể khác từ đó.
Cá nhân tôi nghĩ rằng nó có lý do lịch sử dẫn đến các ngôn ngữ cú pháp dựa trên c, trong đó xor kiến thức của tôi không có mặt hoặc ít nhất là không phổ biến.
Vâng, chỉ cần làm như sau. Giả sử rằng bạn đang giao dịch với booleans A và B, thì giá trị A XOR B có thể được tính bằng JavaScript bằng cách sử dụng như sau
var xor1 = !(a === b);
Dòng trước cũng tương đương với dòng sau
var xor2 = (!a !== !b);
Cá nhân, tôi thích xor1 vì tôi phải gõ ít ký tự hơn. Tôi tin rằng xor1 cũng nhanh hơn. Nó chỉ thực hiện hai phép tính. xor2 đang thực hiện ba phép tính.
Giải thích trực quan ... Đọc bảng dưới đây (trong đó 0 là sai và 1 là đúng) và so sánh cột thứ 3 và thứ 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 |
------------------------------------------
Thưởng thức.
var xor1 = !(a === b);
giống nhưvar xor1 = a !== b;
!(2 === 3)
là true
, nhưng 2
và 3
là sự thật 2 XOR 3
nên được false
.
Thủ tục thanh toán:
Bạn có thể bắt chước nó giống như thế này:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
Làm thế nào về việc chuyển đổi kết quả int thành một bool với phủ định kép? Không quá đẹp, nhưng thực sự nhỏ gọn.
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);
Ngoài ra, tại sao rất nhiều dấu ngoặc đơn? B = !state1 !== !state2;
Hoặc thậm chí bạn có thể bỏ đi sự phủ định:B = state1 !== state2;
state1 !== state2
, thì bạn không cần thực hiện bất kỳ phân vai nào ở đó, vì !==
là một toán tử logic, không phải là một bitwise. 12 !== 4
đúng 'xy' !== true
cũng đúng Nếu bạn sử dụng !=
thay vì !==
, thì bạn sẽ phải thực hiện đúc.
!==
và !=
luôn luôn là boolean ... không chắc sự khác biệt mà bạn tạo ra được cho là gì, đó hoàn toàn không phải là vấn đề. Vấn đề là toán tử XOR mà chúng ta muốn thực sự là biểu thức (Boolean(state1) !== Boolean(state2))
. Đối với booleans, "xy", 12, 4 và true
đều là các giá trị trung thực và nên chuyển đổi thành true
. vì vậy ("xy" XOR true)
nên false
, nhưng ("xy" !== true)
thay vào đó true
, như bạn chỉ ra. Vì vậy, !==
hoặc !=
(cả hai) tương đương với "XOR logic" khi và chỉ khi bạn chuyển đổi các đối số của chúng thành booleans trước khi áp dụng.
Trong hàm xor ở trên, nó sẽ dẫn đến kết quả SIMILAR vì xor logic không chính xác là xor logic, có nghĩa là nó sẽ dẫn đến "sai cho các giá trị bằng nhau" và "đúng cho các giá trị khác nhau" khi xem xét loại dữ liệu phù hợp.
Chức năng xor này sẽ làm việc như xor thực tế hoặc toán tử logic , phương tiện nó sẽ cho kết quả đúng hay sai tùy theo các giá trị truyền là truthy hoặc falsy . Sử dụng theo nhu cầu của bạn
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
(!!x) === (!!y)
. Sự khác biệt là một diễn viên để boolean. '' === 0
là sai, trong khi đó xnor('', 0)
là đúng.
Trong Bản in (Thay đổi + thành giá trị số):
value : number = (+false ^ +true)
Vì thế:
value : boolean = (+false ^ +true) == 1
!!(false ^ true)
hoạt động tốt với booleans. Trong bản đánh máy, + là bắt buộc để làm cho nó hợp lệ !!(+false ^ +true)
.
cond1 xor cond2
tương đương với cond1 + cond 2 == 1
:
Đây là bằng chứng:
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])}`)
}
Lý do không có XOR logic (^^) là vì không giống như && và || nó không cho bất kỳ lợi thế logic-lười biếng. Đó là trạng thái của cả hai biểu thức bên phải và bên trái phải được đánh giá.
Đây là một giải pháp thay thế hoạt động với hơn 2 biến và cung cấp được tính là tiền thưởng.
Đây là một giải pháp tổng quát hơn để mô phỏng XOR logic cho bất kỳ giá trị trung thực / falsey nào, giống như khi bạn có toán tử trong các câu lệnh IF tiêu chuẩn:
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!` );
Lý do tôi thích điều này là bởi vì nó cũng trả lời "Có bao nhiêu trong số các biến này là sự thật?", Vì vậy tôi thường lưu trữ trước kết quả đó.
Và đối với những người muốn hành vi kiểm tra boolean-TRUE xor nghiêm ngặt, chỉ cần làm:
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.
Nếu bạn không quan tâm đến số đếm hoặc nếu bạn quan tâm đến hiệu suất tối ưu: thì chỉ cần sử dụng xor bitwise trên các giá trị được ép buộc thành boolean, cho giải pháp trung thực / giả mạo:
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.
Xin chào, tôi đã tìm thấy giải pháp này, để thực hiện và XOR trên JavaScript và TypeScript.
if( +!!a ^ +!!b )
{
//This happens only when a is true and b is false or a is false and b is true.
}
else
{
//This happens only when a is true and b is true or a is false and b is false
}
Hãy thử cái này ngắn gọn và dễ hiểu
function xor(x,y){return true==(x!==y);}
function xnor(x,y){return !xor(x,y);}
Điều này sẽ làm việc cho bất kỳ loại dữ liệu
true == someboolean
là không cần thiết, vì vậy, thực sự, những gì bạn đã làm là gói những thứ không bằng nghiêm ngặt vào một hàm.
!=
là bạn không thể làm như vậya ^= b
, vìa !== b
chỉ là toán tử bất đẳng thức nghiêm ngặt .