【发布时间】:2019-01-10 16:21:12
【问题描述】:
为什么 JavaScript 在使用连接 + 运算符时优先将操作数强制转换为字符串,但在执行 == 相等检查时优先将操作数强制转换为数字?
'1' + 1 被强制转换为 '1' + '1' 并返回 '11'。
'1' == 1 被强制转换为 1 === 1 并返回 true。
在比较情况下,它们被强制转换为数字,而不是字符串。请参阅以下来源:
1) Douglas Crockford's Encyclopedia
== 运算符产生与此函数相同的结果:
function coercing_equal(left, right) {
if (left === right) {
return true ;
}
if (left === null) {
return right === undefined;
}
if (right === null) {
return left === undefined;
}
if (typeof left === 'number' && typeof right === 'string') {
return left === +right;
}
if (typeof left === 'string' && typeof right === 'number') {
return +left === right;
}
if (typeof left === 'boolean') {
return coercing_equal(+left, right);
}
if (typeof right === 'boolean') {
return coercing_equal(left, +right);
}
if
(typeof left === 'object' &&
(
left.constructor === Number ||
left.constructor === String ||
left.constructor === Boolean
) &&
(typeof right === 'string' || typeof right === 'number')
) {
return coercing_equal(left.valueOf(), right);
}
if (
(typeof left === 'string' || typeof left === 'number') &&
typeof right === 'object' &&
(
right.constructor === Number ||
right.constructor === String ||
right.constructor === Boolean
)
) {
return coercing_equal(left, right.valueOf());
}
return false ;
}
2) MDN
当比较中涉及到类型转换(即非严格比较)时,JavaScript 将 String、Number、Boolean 或 Object 操作数的类型转换如下:
比较数字和字符串时,字符串会转换为数字值。 JavaScript 尝试将字符串数字文字转换为数字类型值。首先,数学值是从字符串数字文字派生的。接下来,将此值四舍五入到最接近的数字类型值。
如果其中一个操作数是布尔值,则布尔操作数如果为真则转换为 1,如果为假则转换为 +0。
如果将对象与数字或字符串进行比较,JavaScript 会尝试返回该对象的默认值。运算符尝试使用对象的 valueOf 和 toString 方法将对象转换为原始值、字符串或数字值。如果转换对象的尝试失败,则会生成运行时错误。
请注意,当且仅当其比较对象是基元时,对象才会转换为基元。如果两个操作数都是对象,则将它们作为对象进行比较,并且只有当两个操作数都引用同一个对象时,相等性测试才为真。
这有什么理由吗,还是只是“因为 JavaScript”的另一种情况?就我目前的理解而言,很难记住。
【问题讨论】:
-
阅读规范。
-
'1' + 1==('1').toString() + (1).toString() -
你怎么知道
'1' == 1被强制转换为1 === 1而不是'1' === '1'? -
@jhpratt “== 中缀运算符”部分伪代码(第 4 和第 5 个 if 语句)。
-
我不会说这只是“因为 javascript”。有一些很好的理由表明我们可能更喜欢一种转换而不是另一种。对于
==,将两者都转换为数字具有很好的特性。例如,比较任意两个虚假值(NaN除外)将返回 true,例如"" == 0。同样,在+的情况下,由于许多字符串不是数字,我宁愿让"foo" + 1成为"foo1"而不是NaN(如果我们将两者都转换为数字)。
标签: javascript types equality coercion