'if condition'内部相等性检查与'console.log'的区别



我正在尝试一个代码片段,console.log语句和条件语句中的空数组检查结果不同。帮助/思考为什么会有所不同?提前感谢!

//Output: true
if([]) {
console.log(true)
} else{
console.log(false)
}
//Output: false
console.log([] == true)

您似乎遇到了一个已知的JavaScript怪癖。

"[]是真的,但不是真的">

问题不在于你在哪里进行评估,而在于这两个看似相同的评估实际上是不同的。

请参阅https://github.com/denysdovhan/wtfjs#-是真的但不是真的

我的假设是,if/else块在其"真实"测试的一部分中,检查是否存在某种东西(而不仅仅是它是否为真(——其中直接控制台打印是将空数组的值与布尔值(这将是假的(进行比较

let test = 'apple';
if( test ){
console.log( 'if/else: ' + true );
}else{
console.log( 'if/else: ' + false );
}
console.log( 'log: ' + ( test == true ) );

这两个片段实际上在做不同的事情,因此产生了不同的结果。

第一种是将[]作为if语句的条件,将数组强制为布尔值。(当然,if只适用于布尔值,如果给定的值还不是布尔值,JS会很乐意转换它。(这就产生了true——JS中的所有对象都是"truthy",包括所有数组。

对于第二个片段,您使用的是"松散相等"运算符==,JS规范为其提供了一组规则,用于如何将值转换为其他类型,最终实现同一类型的两个值之间的直接比较。在这种情况下,您可能希望将非布尔值与truefalse进行比较,从而将非布尔型强制为布尔型,但事实并非如此。规范中所说的是,首先将布尔值强制为数值,从而为true生成1(为false生成0(。因此,它减少到[] == 1——在得到false结果之前,它将经历更多的转换。

关键是在第二种情况下不会发生布尔值的转换。如果你认为这很愚蠢,你可能是对的。这有点棘手,也是许多指南告诉您永远不要在JS中使用==的原因之一。总的来说,我并不同意这个建议(我讨厌门楣告诉我在任何情况下都要使用===(,但你必须意识到一些危险。使用==将值与truefalse进行比较是总是要避免的事情。

幸运的是,如果你想测试x是真是假,你有一个非常简单易懂的方法来做它——你在这里的第一个片段中使用的方法:if (x)

[edit]所以我最初的答案令人困惑,你在互联网上找到的关于这个主题的许多答案都有一些不一致之处;那么,让我再试一次:

第1部分:它们不同的原因

if([](if([]==true(

//Output: false
if([] == true) {
console.log(true);
} else{
console.log(false);
}
//Output: false
console.log([] == true);

第2部分:为什么它很重要AKA:令人困惑的部分

在JS中,以下是一个常见的表达式,用于查看对象/变量是否存在:

var foo = "Hello World";
if (foo) ...

从设计的角度来看,这个测试并不重要,看foo是否等于true或false,它是一个测试,看程序是否能找到对象或变量foo。如果它找到foo,那么它会在"then"条件下执行结果,否则会得到"else"条件。因此,在这种情况下,它将把foo转换为false表示不存在,或者true表示确实存在。因此,在这种情况下,字符串被简化为布尔值。

相比之下:

var foo = "Hello World";
if (foo == true) ...

通常试图找出foo的值是否真的等于true。在这种情况下,您将foo"Hello World"的值与布尔值进行比较,因此在这种情况中,"Hello世界"不等于true。

就像foo一样,[]可以通过多种方式进行求值。空数组仍然是一个对象;因此,在第一种情况下,它强迫为真,因为它想知道[]是否可以被找到;但是,[]也等于['']。所以现在想象一下:

if (['bar'] == 'bar') ...

在这种情况下,JS不会查看['bar']是否存在,而是作为一个包含单个值的对象,可以将其转换为字符串'bar'。

因此:

if([]); // is true because it is an object test that evaluates as (1 === 1)

if([] == true) // is false because it is a string test that evaluates as ('' == 1) to (0 === 1)

最新更新