今天浏览一些技术网站,看到这个题目。虽然觉着代码这么写的可能性低之又低,但是却也考验对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 JavaScript!');
}
</script>

运行代码

最根本的还是强制类型转换。类型==,===运算符和强制转换:

先看个表达式:

<script>
var res = "1.0e0" == { valueOf: function() { return true; } };
  console.log(res);
</script>

运行代码

是的,这个结果也是 true。

对于这个表达式我们能够注意到:

它们的类型是不一样的。原因是在运算的时候进行了强制转换。在比较之前,它们被转换成了数字。

字符串”1.0e0“被解析成数字1,而匿名对象通过调用自身的valueOf方法得到true,然后再转换成数字1。

这也是a可以同时为1,2,3的原因。

我们需要知道的是:

1、如果表达式两边的数据类型不一致,==运算符两边会进行强制转换;

2、此对象在被强制转换时,会自动优先调用了自身的valueOf方法

3、如果此对象没有valueOf方法,则会继续尝试调用toString方法

4、如果将==运算符改成===运算符,则不会强制转换;

5、如果表达式两边数据类型一致,==运算符和===运算符返回的结果是一致的

下图为==运算符针对不同类型参数的强制转换规则:

(a == 1 &amp;&amp; a == 2 &amp;&amp; a == 3),何时为true?-LMLPHP

规则看着挺复杂,不幸的是,它其实也是这么复杂。所以在比较操作中,如果不同类型进行比较,不建议使用==运算符,而是使用严格相等===运算符,因为使用严格相等运算符读者会非常清晰地知道:在比较中没有涉及任何强制转换。否则,你需要读者准确的记住这些强制转换规则以解读代码的行为。

另外一个增加代码可读性的方法就是显示的进行数据类型转换:

代码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函数或者一元运算符 + 将值转换为数字,而不要求读者记住这些转换规则。

04-29 23:35