js 如何使 (aᅠ==1 && a== 2 && a==3) 返回 true?

今天刷博客的时候,看到了一道有趣的面试题“如何使 (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

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值