如果你能确切的答出可以,那恭喜你,你可以绕道了
前言
有人会说,这个问题好奇葩,放在别的语言里,这要是能输出true,估计是见鬼了,但是你别说,放在js中好真有可能。最近在一个人的推特上提了一个问题:
问题:Can (a==1 && a==2 && a==3) ever evaluate to true?
答案:yes
在这篇文章中,我将解释这段代码的原理:
你可以打开chorme浏览器,然后打开开发者模式,在console中输入这段代码,你就可以看到输出结果([windows]: Ctrl + Shift + J [mac]: Cmd + Opt + J)
有什么窍门呢?
其实也没有,能有的就是js中的两个概念:
隐式转换
注意:这题里面我们用的是==而不是===,在js中==代表的是等于而不是全等,那么就存在变量的隐式转化问题。这就意味着结果会比我们所期望的更多的可能性。对于js的隐式转化,真的有很多文章,我推荐一下以下几篇博客,如果你想要了解,可以点进去:
推荐博客
valueOf
我们举个例子:
我们可以对上述对象使用valueOf方法,他会返回一个对象。
是不是很酷,我们可以用typeOf来检测一下这个输出结果的类型:
为了让valueOf可以更方便将一个对象转化成原始值,我们可以重写他,换种说法就是我们可以通过valueOf来返回一个字符串、数字、布尔值等来代替一个对象,我们可以看以下代码:
我们已经重写了原生的valueOf()方法,当我们调用valueOf的时候,他会返回a.num。那我们现在运行以下:
我们得到0了,这很合理,因为0就是赋给a.num的值。那我们可以来做几个测试:
很好,但为什么这个很重要呢?
这很重要,因为当你两种不同类型的遇到相等操作符的时候,js会对其进行类型转化——它企图将操作数的类型转化为类似的。
在我们的问题中: JavaScript会企图将对象转化成数字的类型,进行比较。当要转化的是一个Object的时候,JavaScript会调用valueOf()方法。
自从我们改变了valueOf()方法之后,我们能不能做到以下几点呢:
我们做到了,异常轻松。
现在我们需要做的的一点是:当我们每次去调用a的值的时候,能改变它。
幸运的是,在JavaScript中有 符号。
这个运算符可以轻松的去改变一个的值,我们可以举个简单的例子:
正如你所见的,我们每次使用加法赋值运算符,可以让我们的变量增加。
所以我们可以将这个观念用到valueOf()中。
当我们每次调用valueOf的时候,他会将变量增加1返回给我们。
随着这个改变,我们来运行下面的代码:
这就是它的工作原理。
记住下面两点:
使用相等操作符,js会做强制类型转化
我们的对象每次调用valueOf()它的值会增加1
所以比较的时候我们每次都能得到true。
总结
领取专属 10元无门槛券
私享最新 技术干货