我知道==
运算符执行类型强制。但我无法理解以下行为。
const x = new Boolean(false);
if (x) {
console.log("if(x) is true");
}
if (x == false) {
console.log("if(x == false) is true");
}
令人惊讶的是,在摘要上方显示了两行:
if(x) is true
if(x == false) is true
有人可以解释这种奇怪的行为吗?或者我缺少一些基本的东西?
答案 0 :(得分:4)
如其他答案所述,这是因为x
是一个对象–一个布尔对象,但仍然是一个对象,因为您正在使用new
运算符–并且仅当您比较{ {1}}到x
:false
正在检查if (x)
是否为truthy值,因此不需要强制(不涉及其他操作数):一个对象始终是“ true”(weeeell…几乎总是:x
返回typeof null
,但这是一个虚假的值。但这是另一个故事……)。
您可以轻按toPrimitive符号来轻松检查何时调用强制:
object
答案 1 :(得分:1)
由于Boolean(false)
是一个函数,因此您应该使用new Boolean(false)
而不是Boolean
。
否则,您将得到一个空对象{}
,它与函数本身返回的类型boolean
的类型不同。
const x = new Boolean(false);
const y = Boolean(false);
console.log(x, typeof x);
console.log(y, typeof y);
在您的第一个测试中,您仅检查值是否为真,而空对象是否为真,因为x = {}
,测试通过:
const x = new Boolean(false);
console.log(x, !!x, !!{}, Boolean(x))
if (x) {
console.log("if(x) is true");
}
但是,当使用==
时,运算符使用new Boolean(false)
的{{3}}将false
强制为其原始值,从而相等。
const x = new Boolean(false);
console.log(x.valueOf())
答案 2 :(得分:1)
new Boolean(false)
产生一个对象。即使对象包装虚假的原始值,它们也始终是truthy。例如,尽管new String("")
虚假,""
也是真实的。
另一方面,当您执行new Boolean(false) == false
时,它会将对象强制为其原始值以进行比较。顺便说一句,new Boolean(false) === false
是 not true,因为它们的类型不匹配。
通常,除非有特殊原因,否则不应将对象构造函数用于原始类型,以免发生此类意外行为。
答案 3 :(得分:1)
如果您写
const x = new Boolean(false);
typeof x
将返回object
。类型object
是“ truthy”,这意味着如果没有像==
这样的运算符,则它的值为true。但是,它的值为false
,这就是第二条语句也计算为true的原因。
因此if
语句的行为有所不同,因为没有操作符的if
会检查类型是true还是falsy(在这种情况下为true-> true),以及带有比较(==)的if呼叫.valueOf()
,即false
。
在这种情况下,您都不应使用new
包装器。
const x = false;
就足够了。对于投射,您可以使用Boolean()
,而无需使用new
包装器。
要检查一个值是否真实,可以使用双重否定:
const x = new Boolean(false);
if (x) console.log(!!x);
if (x == false) console.log(x.valueOf());
答案 4 :(得分:1)
当您在javascript中执行if (expression)
时,表达式会通过强制转换为布尔值来评估。
有些困惑,Boolean(new Boolean(false))
的计算结果为true,因为正如尼克所说,它仍然是一个对象。这就是引起您困惑的行为的原因。
好读的书以获得更多信息https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/