为什么在JavaScript中,数字和字符串相加的结果是一个字符串?

16

尝试在JavaScript中使用一些奇技淫巧:

首先我执行了:

console.log("5" + 1);

这会打印出51,这很正常,因为数字和字符串都有一个+运算符,但是因为字符串是第一个变量,所以它会将1转换为字符串。

现在当我做了这个:

console.log(1 + "5")
我原本期望的输出结果是6,因为我以为它会把字符串转换成数字。然而,最终的神奇输出结果是15。
请问有经验的JavaScript程序员能为我解释一下吗?

5
通常情况下,遵循交换律的加法(即使是不同类型的)并不是什么坏事。;-) - linqu
2
可能重复:https://dev59.com/H2025IYBdhLWcg3whGWx(找到的第一个,我确定还有很多) - rlemon
2
@linqu 请注意,这个操作不是可交换的,因为"5" + 1 == "51" != "15" == 1 + "5" - Bakuriu
这确实是一些奇怪的行为。 - Robin-Hoodie
@Bakuriu 说得好!我指的是不会改变的数据类型。但确实,结果是在改变的。 - linqu
显示剩余2条评论
5个回答

27

引用 ECMAScript 规范 加法操作符 (+) 部分:

  1. 如果 lprim 的类型是 String 或 rprim 的类型是 String,则
    返回将 ToString(lprim) 和 ToString(rprim) 连接而成的字符串。

因此,这里的顺序不重要。


6
为什么会是奇怪的呢?如果有一个字符串,那么结果也将是一个字符串。容易记住。如果结果取决于操作数的顺序,那才会让人感到奇怪。 - dfsq
3
很不幸的是,当一个运算符可以被重复使用时,语言设计者必须为每种情况选择一条规则。我认为这比 2 + "Hello" 变成 2 + "Hello" 的 ASCII 值 要好。 - Sarima
1
@Joshpbarron:什么鬼是“'Hello'的ASCII值”?? - Lightness Races in Orbit
1
072 101 108 108 111 @LightnessRacesinOrbit(注:这是一个编程相关的内容,无需翻译成中文) - Sarima
2
@LightnessRacesinOrbit,为了一百万条评论,你是正确的。 - Sarima
显示剩余7条评论

8

console.log(1 + "5") 我原本期望输出结果为6,因为我认为它会将字符串转换为数字。...

但如果你写了以下代码,你会得到什么结果呢?

console.log(1 + " fine day")

或者

console.log(1 + " answer(s) to my question")

一般情况下不能保证将字符串转换为数字是可行的。但任何数字都可以被转换为字符串。这就是为什么转换规则被写成向兼容类型移动的方式。在您作为程序员知道字符串可以安全地转换为数字的上下文中,您可以显式地进行转换,以使+操作在两个数字之间。但这通常不适用于字符串。
在其他情况下,这也是为什么在处理混合类型时,小整数和低精度浮点数会被转换为大整数或双精度浮点数的原因。您可以安全地将有限形式转换为更大的形式,但通常不能反过来转换。一个小的整数可以表示为大整数或双精度浮点数,但反向转换通常不是安全的转换。
因此,在处理混合类型的操作的转换规则中,尽可能地编写了朝着相互兼容且安全的常见类型移动的方式。程序员需要对特殊情况编写显式转换,并确保更通用的类型可以安全地转换为更有限的类型。

2
在这两种情况下,值将被转换为字符串。当您将数字添加到字符串或将字符串添加到数字时,结果是一个字符串。
只需使用parseInt(value)toString(value) 强制转换即可。

好的回答,除了没有引用! - Lightness Races in Orbit

1
你可以尝试以下代码:
console.log(1 + parseInt("5")) => 6

-6

在Javascript中,连接字符串也使用+

var result = "String" + number + obj;
// is equivalent to
string result = "String" + number.ToString() + obj.ToString();

然而事实是,在C# / .net中,您可以做同样的事情,并且会得到相同的结果 - System.Console.WriteLine("result is " + 10 + 20);.

在JavaScript中(以及C#),字符串是不可变的。它们永远不能被更改,只能用其他字符串替换。您可能已经知道,合并+“String”不直接修改合并变量 - 操作创建一个新字符串,该字符串是连接两个字符串的结果,但如果要更改它,则必须将该新字符串分配给合并变量。

关于使用数学运算符进行字符串连接的争论可以说是一个“错误”的争论,但也有人认为,使用+进行大量字符串连接可能非常缓慢。


但是也有人认为,使用“+”进行大量字符串连接可能会非常慢。然而,这种说法现在已经不太准确了。http://jsperf.com/string-concat-without-sringbuilder/5 这个链接是我从这个答案中得到的。 - rlemon
11
这如何回答问题了? - nhahtdh
1
我不明白为什么会有这么多的踩,我只是在回答提问者的问题时给出了一个简单的解释!!!这是什么鬼!! - Nadeem_MK
1
@nhahtdh的评论解释了为什么有人给你点了踩。你没有回答问题。问题并不是关于像你所想的那样使用数学运算符进行字符串连接。 - Darko
如果是这样,那为什么原帖的作者会选择它作为答案呢?只有在你开始投反对票之后他才改变了答案!! - Nadeem_MK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接