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;
var1 = a;
var2 = a;
var3 = 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