今天刷博客的时候,看到了一道有趣的面试题“如何使 (aᅠ==1 && a== 2 && a==3) 返回 true”,咋一眼看过去,觉得非常的unbelievable!!!
看了别人给的答案之后,陷入了沉思。。。然后感叹一声:原来如此!
我们来看看大神们的脑洞吧~
解法一:对象类型转换
var a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('It is amazing!');
}
试试在控制台试一下,你或许同样会感到 amazing。
这里面是利用的js的类型转换规则,当两个类型不同时进行==比较时,会将一个类型转为另一个类型,然后再进行比较。·比如 Object 类型与 Number 类型进行比较时,Object 类型会转换为 Number 类型。转换为时会尝试调用 Object.valueOf 和 Object.toString 来获取对应的数字基本类型。
上面的转换逻辑是先调用valueOf
方法,如果返回的还是对象,再接着调用toString
方法。每次比较时候都会执行方法返回 a
的 i
属性同时也改变 i
的值,所以上面 if
执行完以后 a
的 i
属性已经变为了 4。
上面的解法是重写了对象 a 的 toString 方法,当然,你要重写 valueOf 方法也可以,运行的结果都是一样的。
解法二:数组类型转换
var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
console.log('It is amazing!');
}
这种解法还是比较巧妙的,我们知道 array
也属于对象,应该和对象的规则一样。但是这方法没有重写 toString/valueOf,它利用了数组的 toString 会隐含调用 Array.join 方法。
对于数组对象,toString 方法返回一个字符串,该字符串由数组中的每个元素的 toString 返回值经调用 join 方法连接(由逗号隔开)组成。
数组调用 toString 会隐含调用 join 方法。而数组 shift 方法的用法:shift 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。如果数组是空的,那么 shift 方法将不进行任何操作,返回 undefined 值。请注意,该方法不创建新数组,而是直接修改原有的 arrayObject。
所以我们可以看到 a==1
时会调用 toString,toString 调用 join,join 等于 shift,则转换为 Number 后为1。
解法三:定义"a"属性,并重写它的getter方法
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if(a == 1 && a == 2 && a == 3) {
console.log('It is amazing!');
}
使用一个 get,让 a 的返回值为三个不同的值。
解法四:字符编码
利用Unicode的字符编码:同义字和隐形字符。
同义字:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
console.log("It is amazing!");
}
隐形字符:
var a = 1;
var a = 2;
var a = 3;
console.log(a == 1 && a == 2 && a == 3);
/****
var a = 1;
var a\u200c = 2;
var a\u200d = 3;
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);
****/
其他千奇百怪的解法
function A() {
var value = 0;
this.valueOf = function () { return ++value; };
}
var a = new A;
if (a == 1 && a == 2 && a == 3) {
console.log('It is amazing!');
}
/** ES6版 **/
class A {
constructor() {
this.value = 0;
this.valueOf();
}
valueOf() {
return this.value++;
};
}
let a = new A;
if (a == 1 && a == 2 && a == 3) {
console.log('It is amazing!');
}
var a = 1;
var ᅠ1 = a;
var ᅠ2 = a;
var ᅠ3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );
更多神奇的例子,可以参考 stackoverflow 的讨论:
https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true/48274520#48274520