When I saw this topic for the first time, I was shocked. I analyzed the common sense of our programming and thought it was a
. The variable 0617b2c051c64c should be equal to 1, 2 and 3 at the same time under the same circumstances. These three values, this is a fantasy, no less than Goldbach 1+1=1
, but everything is possible, out of curiosity, after thinking for a long time, I decided to try a solution.
My idea comes from another similar interview question I encountered earlier:
// 设置一个函数输出一下的值
f(1) = 1;
f(1)(2) = 3;
f(1)(2)(3) = 6;
The solution at the time was to use toString
or valueOf
, so let’s review the toString
and valueOf
methods, so that we can get a deeper understanding of this type of problem:
For example, if we have an object, without rewriting the toString()
method and the valueOf()
method, the output result in Node or the browser is like this
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
best | Person |
best.toString() | [object Object] |
best.valueOf() | Person |
best + 'GiGi' | [object Object]GiGi |
From the above output, we can observe a detail, toString()
outputs [object Object]
, and valueOf()
outputs Person
object itself, and when the operation reaches best + 'GiGi'
, it turns out that it outputs [object Object]GiGi
and we can infer that the toString()
object is initially obtained by calling 1c78617b. +
workmanship for the calculation of the string?
In order to verify our inference in the previous step, we made a little change and valueOf
method once:
class Person {
constructor(name) {
this.name = name;
}
// 复写 valueOf 方法
valueOf() {
return this.name;
}
}
best | Person |
best.toString() | [object Object] |
best.valueOf() | Person |
best + 'GiGi' | KobeGiGi |
This time, there is only one different result from the above, that is, the last best + 'GiGi'
after copying the valueOf()
have changed, from which we can see that the nature of the object has not fundamentally changed, but When it is used as a direct operation, its value is obtained from the overwritten valueOf()
, and continues to participate in subsequent operations.
Of course, don’t forget that we also have a toString()
method, so we also duplicate it to see if the result will also be affected:
class Person {
constructor(name) {
this.name = name;
}
valueOf() {
return this.name;
}
toString() {
return `Bye ${this.name}`;
}
}
best | Person |
best.toString() | Bye Kobe |
best.valueOf() | Kobe |
best + 'GiGi' | KobeGiGi |
We found that best + 'GiGi'
still hasn’t changed, or use the result of valueOf()
In fact, we have rewrote the valueOf
method, which does not necessarily call the return value of valueOf()
Instead valueOf
will be calculated according to this value when it is of the basic data type. If it is not the basic data type, the value returned by the toString()
class Person {
constructor(name) {
this.name = name;
}
valueOf() {
return this.name;
}
toString() {
return `Bye ${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
best | Person |
best.toString() | Bye [object Object] |
best.valueOf() | {name: "Kobe"} |
best + 'GiGi' | Bye [object Object]GiGi |
Looking at the above example, the incoming name
is an object new Person({ name: "Kobe" })
, which is not a basic data type, so when performing an addition operation, toString()
method is used for calculation. Of course, if there is no valueOf()
method, the method will execute toString()
.
So after laying the groundwork for so long, we have to uncover the answer. We are using the above principles to answer this question:
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!");
}
Here is relatively simple, directly rewrite the toString()
method, because there is no valueOf()
, when he does the calculation to judge a == 1
, the result of toString()
will be executed.
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!");
}
Of course, you don’t need to use toString
, and you can replace it with valueOf
. The effect is the same:
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!");
}
Therefore, when an object is performing operations (such as adding, subtracting, multiplying, valueOf()
, and judging equality), there will often be a call problem of 0617b2c051ca5a or toString
. There is usually a function hidden behind the variable of this object.
Of course, the principle of the following question is actually the same, and the solution is attached:
// 设置一个函数输出一下的值
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
Of course, it is not over yet. There are some special solutions here. In fact, when using objects, if the object is an array, then the above logic will still be established, but at this time toString()
will become an implicit call to the join()
method. In other words, if the object is an array, when you do not rewrite other toString()
methods, the default implementation is to call the array's join()
method return value as the return value of toString()
, so there is a new solution for this problem, which is Without copying toString()
, copy the join()
method and turn it into the shift()
method, which allows the first element of the array to be deleted from it 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!");
}
We explore the road is not over, attentive students will find our topic is how to make (a === 1 && a === 2 && a === 3) is true, but above all to discuss easing equal
==
case , In ===
, will the above result be different?
The answer is different, you can try to change the above loose conditions to strict debugging and try again to know the result.
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!"); // Hi Eno!此时再也没出现过了
}
So how should we solve the situation at this time? We can consider using Object.defineProperty
to solve this problem. This Vue
. It is also a common knowledge point in interviews now. We can use it to hijack the a
variable, and let it increase when we get it's worth. , Then the problem can be easily solved:
var value = 1;
Object.defineProperty(window, "a", {
get() {
return this.value++;
}
});
if (a === 1 && a === 2 && a === 3) {
console.log("Hi Eno!");
}
We are hijacking top global window
above a
, when a
every time to make a judgment will trigger get
property acquisition value, and each time get the value of a function will be triggered by the implementation of a self-judgment or three times since increased three times, the final will The formula holds.
Of course, there are other methods here. Here is another example, such as using hidden characters to hide from the interviewer:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if (aᅠ == 1 && a == 2 && ᅠa == 3) {
console.log("Hi Eno!");
}
The above solution is very confusing. If you are not careful, you will think that there are three identical a
. In fact, it essentially defines three different a
values. There are hidden characters before and after a
Copy and paste the above code to debug. If you are Chrome
in 0617b2c051cbc3, you can use special means to a
, and when you press Enter, the debugging tool will hide these traces, so as to hide from the sky and show it for a while. The interviewer who hasn't reacted for a while.
Finally, I wish everyone a good job in the new year. The above code is basically not used in actual situations, but JS
. Interviewers are also recommended Don't use this kind of interview questions to make it difficult for the interviewer~
If the articles and notes can bring you a hint of help or inspiration, please don’t be stingy with your likes and collections, yours is definitely the biggest motivation for me to move forward😁
A link to the notes is attached. Read more high-quality articles in the past and you can move to view it. If you like, you can give me a thumbs up and encouragement:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。