为什么此代码评估为:
10 + "10" => "1010"
"10" + 10 => "1010"
为什么它不能这样工作:
10 + "10" => 20 // the number comes first
"10" + 10 => "1010" // the string comes first
编辑:
更具体地说,在解释器的实现中,它在哪里执行此操作?或者,它是如何做到的?
为什么此代码评估为:
10 + "10" => "1010"
"10" + 10 => "1010"
为什么它不能这样工作:
10 + "10" => 20 // the number comes first
"10" + 10 => "1010" // the string comes first
编辑:
更具体地说,在解释器的实现中,它在哪里执行此操作?或者,它是如何做到的?
+
是一个连接运算符,也是 Javascript 中的算术运算符。如果它发现在字符串和数字之间使用了该运算符,那么它将该数字连接到字符串中,否则如果您将运算符用于两个整数,那么结果也将是整数。
所以,
字符串 + 字符串 = 字符串
字符串 + 整数 = 字符串
整数 + 字符串 = 字符串
整数 + 整数 = 整数
ECMAScript 262 规范编纂了 JavaScript 语言(JavaScript 实际上是 ECMAScript 的 Mozilla 实现)。无论如何,在我通常参考的Annotated ES5中,事情相对容易找到。
请参阅11.6.1 加法运算符 (+):
加法运算符执行字符串连接或数字加法。
产生式 AdditiveExpression : AdditiveExpression + MultiplicativeExpression 的评估如下:
- 令 lref 为 AdditiveExpression 求值的结果。
- 令 lval 为 GetValue(lref)。
- 令 rref 为评估 MultiplicativeExpression 的结果。
- 设 rval 为 GetValue(rref)。
- 令 lprim 为 ToPrimitive(lval)。
- 令 rprim 为 ToPrimitive(rval)。
- 如果 Type(lprim) 是 String 或 Type(rprim) 是 String,则返回作为连接 ToString(lprim) 后跟 ToString(rprim) 的结果的 String
- 返回对 ToNumber(lprim) 和 ToNumber(rprim) 应用加法运算的结果。请参见 11.6.3 下方的注释。
在比较具有不同类型的值时,JavaScript 使用一组复杂且令人困惑的规则。通常,它只是尝试将其中一个值转换为另一个值的类型(正如我们在您的问题中看到的那样)。这通常被称为自动类型转换。
让我们看一下您的代码:
10 + "10" => "1010"
"10" + 10 => "1010"
在 JavaScript 中,如果将任何非字符串值添加到字符串中,则该值会在连接之前自动转换为字符串。因此,无论您的整数或字符串值的顺序如何,JavaScript 都将任何整数视为字符串。
但是,您应该知道,JavaScript 并不将此应用于所有算术运算符。例如,如果我们将我们的值相乘,我们会得到:
10 * "10" => 100
"10" * 10 => 100
"ten" * 10 => NaN
现在,为什么 Javascript 会这样做?好吧,你可以说这是为了方便。在很多情况下,您可能需要将两个值连接成一个字符串。相反,您永远不能将整数与字符串相乘,正如我们在上面的最后一个示例中所见。
不幸的是,这就是 Javascript 的工作方式