(a == 1 && a == 2 && a == 3),何时为true?
今天浏览一些技术网站,看到这个题目。虽然觉着代码这么写的可能性低之又低,但是却也考验对js了解的程度。
在 JavaScript 中 (a ==1 && a== 2 && a==3) 可能为 true 吗?解释说nothing is impossible!
这里是两个可能的答案:
<script> const a = { i: 1, toString: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } </script>
<script> const a = { i: 1, valueOf: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } </script>
最根本的还是强制类型转换。类型==,===运算符和强制转换:
先看个表达式:
<script> var res = "1.0e0" == { valueOf: function() { return true; } }; console.log(res); </script>
是的,这个结果也是 true。对于这个表达式我们能够注意到:它们的类型是不一样的。原因是在运算的时候进行了强制转换。在比较之前,它们被转换成了数字。字符串”1.0e0“被解析成数字1,而匿名对象通过调用自身的valueOf方法得到true,然后再转换成数字1。我们需要知道的是:
1、如果表达式两边的数据类型不一致,==运算符两边会进行强制转换;
2、此对象在被强制转换时,优先调用了自身的valueOf方法;(如果此对象没有valueOf方法或对象的valueOf返回的是false,则以上表达式结果为false)
3、如果此对象没有valueOf方法,则会继续尝试调用toString方法
4、如果将==运算符改成===运算符,则不会强制转换;
5、如果表达式两边数据类型一致,==运算符和===运算符返回的结果是一致的
下图为==运算符针对不同类型参数的强制转换规则:
规则看着挺复杂,不幸的是,它其实也是这么复杂。所以在比较操作中,如果不同类型进行比较,不建议使用==运算符,而是使用严格相等===运算符,因为使用严格相等运算符读者会非常清晰地知道:在比较中没有涉及任何强制转换。否则,你需要读者准确的记住这些强制转换规则以解读代码的行为。
另外一个增加代码可读性的方法就是显示的进行数据类型转换:
代码1:
var today = new Date(); if(form.month.value == (today.getMonth() + 1) && form.day.value == today.getDate()){ //happy birthday... }
代码2:
var today = new Date(); if(+form.month.value === (today.getMonth() + 1) && +form.day.value === today.getDate()){ //happy birthday... }
很显然,代码2更加清晰地向读者传达了代码在做什么样的转换,它只是显示的使用Number函数或者一元运算符 + 将值转换为数字,而不要求读者记住这些转换规则。