This is the 26th day of my participation in the More Text Challenge. For more details, see more text Challenge
How can a == 1 && a == 2 && a == 3 return true?
- Problem description
- Is it possible for (a == 1 && a == 2 && a == 3) to be true in JavaScript?
Reference implementation
Reference solution: a is an object or function, each call value is different, to order the rule of change can achieve more etc
Scheme 1 Numeric variable name
var a = 1;
var ᅠ1 = a;
var ᅠ2 = a;
var ᅠ3 = a;
console(a = = ㅤ.log1&& a = = ㅤ2&& a = = ㅤ3 );
Copy the code
Option 2 overwrites valueOf()
var a = {
value: 1.valueOf: function() {
return this.value++;
}
}
(a == 1 && a == 2 && a == 3); // true
Copy the code
-
Solutions that
-
On the face of it, valueOf() should be called every time, but why? We didn’t call it.
-
Why is valueOf called here?
-
Cause Reference == Conversion rule
-
If one is null and one is undefined, they are equal
-
If one is a number and one is a string, first convert the string to a number and then compare the converted value
-
If one of these values is true, it is converted to 1 and compared; If one of the values is false, this converts to 0 and compares
-
If one value is an object and the other is a number or string, the object is converted to the original value and compared. When converted to a string, toString() is called first, and valueOf() is called if there is no toString() method or if it returns a non-primitive value. If there is still no toString() method or if it returns a non-primitive value, a type error exception is thrown. The original value returned is converted to a string; If converted to a number, it is similar, except that valueOf() is called first, then toString() is called, and the original value returned is converted to a number
-
Comparisons between the other types are not equal
-
So comparing a to these characters here will be converted to a number, and by default the string method valueOf() will be called, which we override to intercept the valueOf processing a
-
The same can be done with the toString method, because translating a string to a number involves valueOf() and toString(), for the same reason
-
let a = {
value: 1.toString: function () {
return a.value++; // Why don't you use this? Because this scope is variable}}console.log(a == 1 && a == 2 && a == 3); // true
Copy the code
- As long as it conforms to the increasing rule, a can achieve multiple equality, because this A is not that A
Solution 3 ES6 Proxy
var a = new Proxy({ i: 0 }, {
get: (target, name) = > name === Symbol.toPrimitive ? () = > ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3); // true
Copy the code
Scenario three uses getter memory
var temp = 1;
Object.defineProperty(window.'a', {
get: function() { // Temp +1 for each value
return this.temp++
}
});
(a == 1 && a == 2 && a == 3); // true
(a === 1 && a === 2 && a === 3); // true
Copy the code
- Solutions that
- This is the way to use getter memory, which is to store a value in the global variable temp, and every time you call it ++1 so that the call a increments by 1 every time
Join + shift
- When comparing an array of objects, array A will call toString() by default, and toString() will call join() by default. Here join() will be changed to shift(), which means that the first array element is deleted and returned
- So every time you call this, you’re going to remove the first value from array A and you’re going to return the deleted value, and in combination with that, you’re going to get the corresponding position for each comparison
- This is 1, 2, 3, whatever the rule returns
var a =[1.2.3];
a.join = a.shift;
console.log(a); // (3) [1, 2, 3, join: ƒ]
// console.log(a ==ㅤ1 && a ==ㅤ2 && a ==ㅤ3); // true
console.log(a == 1); // true
console.log(a); // (2) [2, 3, join: ƒ]
console.log(a == 2); // true
console.log(a); / / / 3, the join: ƒ
console.log(a == 3); // true
console.log(a); / / / join: ƒ
Copy the code