究竟为什么这里的条件评估为真?
var condition = new Boolean(false);
if (condition == !condition)
alert("The more you know...");
答案 0 :(得分:24)
分解:
var condition = new Boolean(false);
这实际上是一个对象,condition.valueOf() === false
!{}
评估为false,因为{}
为真(解释http://www.ecma-international.org/ecma-262/5.1/#sec-9.2)
所以检查是condition.valueOf() == false
,这是真的
答案 1 :(得分:23)
您正在将对象(LHS)与布尔false
(RHS)进行比较。
[object Boolean] == false
==
运算符根据ECMAScript定义的抽象等式比较算法执行类型强制。 11.9.3抽象等式比较算法
与您的代码相关的是该算法的以下几点(其中x是LHS,y是RHS)。
7)如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)。
请注意,它实际上首先尝试将布尔值转换为数字。 false
布尔值转换为数字0
,现在我们有了这个:
[object Boolean] == 0
如您所见,由于==
,它递归地输入相同的算法。所以现在我们将一个对象与一个数字进行比较,因此适用以下几点:
9)如果Type(x)是Object而Type(y)是String或Number, 返回比较结果ToPrimitive(x)== y。
所以现在它正在尝试将对象强制转换为原始值。从 9.1 ToPrimitive ,在对象上调用时:
对象返回Object的默认值。通过调用对象的[[DefaultValue]]内部方法,传递可选提示PreferredType来检索对象的默认值。 [[DefaultValue]]内部方法的行为由本规范为8.12.8中的所有本机ECMAScript对象定义。
所以你可以看到它想要对象的[[DefaultValue]]
。这将我们带到 8.12.8 [[DefaultValue]] ,它需要一个“提示”。因为它没有收到“提示”,所以它的行为就像提示是“数字”一样。
当没有提示调用O的[[DefaultValue]]内部方法时,它的行为就好像提示是数字,...
这样就会带来以下行为:
当使用提示号调用O的[[DefaultValue]]内部方法时,将执行以下步骤:
设valueOf是使用参数“valueOf”调用对象O的[[Get]]内部方法的结果。
- 醇>
如果IsCallable(valueOf)为真,那么
一个。设val是调用valueOf的[[Call]]内部方法的结果,其中O为此值和空参数列表。
湾如果val是原始值,则返回val。
所以它调用对象上的.valueOf()
方法,将我们带到 15.6.4.3 Boolean.prototype.valueOf()
设B为此值。
如果Type(B)是布尔值,则令b为B。
如果Type(B)是Object并且B的[[Class]]内部属性的值是“Boolean”,那么令b为B的[[PrimitiveValue]]内部属性的值
否则抛出TypeError异常。
- 醇>
返回b。
因此,您可以从第3步看到它将返回对象的[[PrimitiveValue]]
。这将我们带到 15.6.2.1 new Boolean(value)
新构造的Boolean对象的[[PrimitiveValue]]内部属性设置为ToBoolean(value)。
因此您可以看到,您最终会获得最初传递给构造函数的值的ToBoolean
值,即false
。它的ToBoolean
值显然是false
,所以现在你的比较是:
false == 0
由于类型仍然不匹配,它将转到原始算法中的第6点:
6)如果Type(x)是布尔值,则返回比较结果ToNumber(x)== y。
所以它现在想要将布尔值false
转换为数字。这与上面所做的类似。值false
会转换为值0
,因此现在我们有:
0 == 0
最后我们有一个类型匹配的比较,因此通过比较值,它的行为与严格的===
对应物相同。显然,0
确实等于0
,因此我们得到true
。
故事的道德......当你在JavaScript中询问“为什么”时,这就是你得到的。
答案 2 :(得分:7)
只是阅读逻辑布局的规范真的很有帮助,参见
开始于:
var x = new Boolean(false);
var y = !x;
然后
y = false;
因为布尔对象不被认为是布尔值而是日常对象,ToBoolean(x)
evaluates to true
和!true
evaluates to false
The Abstract Equality Comparison Algorithm
第1轮:第7步
如果Type(y)是布尔值,则返回比较结果x == ToNumber(Y)。
y = 0; //ToNumber(false) is 0
第2轮:第9步
如果Type(x)是Object而Type(y)是String或Number,则返回 比较结果ToPrimitive(x)== y。
x = false //Basically ends up calling x.valueOf()
第3轮:第6步
如果Type(x)是布尔值,则返回比较结果ToNumber(x) == y。
x = 0; //ToNumber(false) is 0
最后:第1步
如果Type(x)与Type(y)相同,那么
步骤1 C
如果Type(x)是Number,那么
步骤1 C iii
如果x与y的数值相同,则返回true。
答案 3 :(得分:4)
我从The Abstract Equality Comparison Algorithm学到的一件事是,忘记直觉,并按照步骤进行。
由于对象是真实的,它们的否定是false
,因此算法的内容是:
Boolean(false) == false
如果你一步一步走,你会得到:
Boolean(false) == 0 // Step 7
false == 0 // Step 9
0 == 0 // Step 6
true