When I first saw this topic, I am more shocked, analyses the programming is not under our common sense, and that is unlikely, variable a to be in the same situation at the same time is equal to 1, 2, and 3 of the three values, this is a fable, as 1 + 1 = 1 goldbach conjecture, but everything is possible, out of curiosity, After much thought I decided to try a solution.

I got the idea from a similar interview question I encountered earlier:

// Set a function to output the following value
f(1) = 1;
f(1) (2) = 3;
f(1) (2) (3) = 6;
Copy the code

The solution at the time was toString or valueOf, so let’s review toString and valueOf methods to get a better understanding of this type of problem:

Let’s say we have an object that, without overwriting the toString() and valueOf() methods, will output something like this from Node or the browser

class Person {
  constructor() {
    this.name = name; }}const best = new Person("Kobe");
console.log(best); // log: Person {name: "Kobe"}
console.log(best.toString()); // log: [object Object]
console.log(best.valueOf()); // log: Person {name: "Kobe"}
console.log(best + "GiGi"); // log: [object Object]GiGi
Copy the code
best Person
best.toString() [object Object]
best.valueOf() Person
best + ‘GiGi’ [object Object]GiGi

ToString () outputs [object object], valueOf() outputs the Person object itself, and best + ‘GiGi’ outputs GiGi. The toString() method is called by the toString() operator.

To verify our previous assumption, let’s rewrite the valueOf method with a slight change:

class Person {
  constructor(name) {
    this.name = name;
  }
  // Override the valueOf method
  valueOf() {
    return this.name; }}Copy the code
best Person
best.toString() [object Object]
best.valueOf() Person
best + ‘GiGi’ KobeGiGi

The only difference this time is that the best + ‘GiGi’ result has been changed after the valueOf() method has been overridden. We can see that the nature of the object has not changed fundamentally, but when it is used as a direct operation, Its value is taken from valueOf(), which is copied, and continues to participate in subsequent operations.

Of course, don’t forget that we also have a toString() method, so let’s also overwrite it to see if the result is affected as well:

class Person {
  constructor(name) {
    this.name = name;
  }
  valueOf() {
    return this.name;
  }
  toString() {
    return `Bye The ${this.name}`; }}Copy the code
best Person
best.toString() Bye Kobe
best.valueOf() Kobe
best + ‘GiGi’ KobeGiGi

We find that best + ‘GiGi’ remains unchanged, using the result of the last valueOf() we overwrote

In fact, we overwrite the valueOf method. We do not necessarily call the return valueOf valueOf() to evaluate. Instead, valueOf returns a value that is a basic data type, and if it is not, the value returned by the toString() method is used.

class Person {
  constructor(name) {
    this.name = name;
  }
  valueOf() {
    return this.name;
  }
  toString() {
    return `Bye The ${this.name}`; }}const best = new Person({ name: "Kobe" });

console.log(best); // log: Person name: {name: "Kobe"}
console.log(best.toString()); // log: Bye [object Object]
console.log(best.valueOf()); // log: Person {name: "Kobe"}
console.log(best + "GiGi"); // log: [object Object]GiGi
Copy the code
best Person
best.toString() Bye [object Object]
best.valueOf() {name: “Kobe”}
best + ‘GiGi’ Bye [object Object]GiGi

Look at the example above. Now the name passed in is an object new Person({name: “Kobe”}), is not a basic data type, so when the addition operation is performed, the value returned by toString() is evaluated. Of course, if there is no valueOf() method, toString() is executed.

So, after all this preparation, we’re going to find the answer, and we’re going to use these principles to solve this problem:

class A {
  constructor(value) {
    this.value = value;
  }
  toString() {
    return this.value++; }}const a = new A(1);
if (a == 1 && a == 2 && a == 3) {
  console.log("Hi Eno!");
}
Copy the code

Here it’s easier to rewrite toString(), because there’s no valueOf(), and it executes the toString() result when it evaluates a == 1.

class A {
  constructor(value) {
    this.value = value;
  }
  valueOf() {
    return this.value++; }}const a = new A(1);
if (a == 1 && a == 2 && a == 3) {
  console.log("Hi Eno!");
}
Copy the code

Of course, instead of using toString, you could use valueOf to get the same effect:

class A {
  constructor(value) {
    this.value = value;
  }
  valueOf() {
    return this.value++; }}const a = new A(1);
console.log(a);
if (a == 1 && a == 2 && a == 3) {
  console.log("Hi Eno!");
}
Copy the code

Therefore, when an object performs operations (such as addition, subtraction, multiplication, division, and equality), it often has the problem of calling valueOf() or toString. The object’s variable usually has a function hidden behind it.

Of course, the following principle is also the same, with the solution:

// Set a function to output the following value
f(1) = 1;
f(1) (2) = 3;
f(1) (2) (3) = 6;

function f() {
  let args = [...arguments];
  let add = function() { args.push(... arguments);return add;
  };
  add.toString = function() {
    return args.reduce((a, b) = > {
      return a + b;
    });
  };
  return add;
}
console.log(f(1) (2) (3)); / / 6
Copy the code

Of course, we’re not done yet. There are some special ways to do this. In fact, when you use an object, the same logic holds if the object is an array, but the toString() method is implicitly called join(). When you do not override other toString() methods, the default implementation is to call the join() method of the array as the return value of toString(), so a new solution is to override join() without overwriting toString(). Change it to shift(), which removes the first element from the array and returns the value of the first element.

class A extends Array {
  join = this.shift;
}
const a = new A(1.2.3);
if (a == 1 && a == 2 && a == 3) {
  console.log("Hi Eno!");
}
Copy the code

If a===1&&a== 2&&a===3) = true, the result is different for strict equality ===2.

And the answer is different, so you can try changing the loose condition to strict debugging and try again and see what happens.

class A extends Array {
  join = this.shift;
}
const a = new A(1.2.3);
// if === ==
if (a === 1 && a === 2 && a === 3) {
  console.log("Hi Eno!"); // Hi Eno! It never happened again
}
Copy the code

So how to solve the situation at this time? We could consider using Object.defineProperty, which is known by Vue and is now a cliche in interviews. We could use it to hijack the A variable and increment it when we get the value of it and the problem would be solved:

var value = 1;
Object.defineProperty(window."a", {
  get() {
    return this.value++; }});if (a === 1 && a === 2 && a === 3) {
  console.log("Hi Eno!");
}
Copy the code

When A makes a judgment, it will trigger the get attribute to obtain the value, and every time it gets the value, it will trigger the function to implement an increment. After three judgments, the increment will be three times. Therefore, the formula will be valid in the end.

Of course, there are other methods, here is another example, such as using hidden characters to trick the interviewer:

varA ㅤ =1;
var a = 2;
varㅤ a =3;
if(a ㅤ = =1 && a == 2&& ㅤ = = a3) {
  console.log("Hi Eno!");
}
Copy the code

Above the focus of this method is very strong, if not careful can be thought as an a, three in essence is to define a value of the three different, a hidden characters before and after, so debugging, please copy and paste the above code debugging, his play in Chrome hand can use special means to make one or two placed behind a red dot, And when you hit the car, the debugging tool will hide the traces, so that the interviewer is not aware of it for a moment.

Finally, I wish you all to find a good job in the New Year. The above code will not be used in practical situations, but it is instructive to explore the infinite possibilities of JS. It is also recommended that interviewers do not use this kind of interview questions to confuse the candidates

If the article and notes can bring you a little help or inspiration, please do not spare your likes and favorites, you are sure to be my biggest motivation 😁

Attached note link, read past more quality articles can be moved to view, like you can give me a point to encourage oh:

  • Github.com/Wscats/CV/i…