为什么 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中?

IT技术 javascript arrays string concatenation
2021-01-30 16:52:22

我想将一个数组的元素添加到另一个数组中,所以我尝试了这个:

[1,2] + [3,4]

它的回应是:

"1,23,4"

到底是怎么回事?

6个回答

+操作者没有为数组定义

发生的事情是 Javascript将数组转换为字符串并将它们连接起来。

 

更新

由于这个问题以及因此我的回答受到了很多关注,我觉得概述一下+操作员的一般行为也是有用的和相关的

所以,它来了。

排除 E4X 和特定于实现的东西,Javascript(从 ES5 开始)有6 种内置数据类型

  1. 不明确的
  2. 空值
  3. 布尔值
  4. 数字
  5. string
  6. 目的

请注意,尽管Null 和可调用对象的typeof 返回有些令人困惑 ,但Null 实际上不是对象,严格来说,在符合规范的 Javascript 实现中,所有函数都被视为对象。objectfunction

没错 - Javascript 本身没有原始数组只有Array使用一些语法糖调用的 Object 实例才能减轻痛苦。

更令人困惑的是,诸如new Number(5),new Boolean(true)new String("abc")object类的包装实体都是类型,而不是人们可能期望的数字、布尔值或字符串。尽管如此,对于算术运算符NumberBoolean表现为数字。

容易吧?完成所有这些之后,我们可以继续进行概述本身。

+按操作数类型的不同结果类型

            || undefined | null   | boolean | number | string | object |
=========================================================================
 undefined  || number    | number | number  | number | string | string | 
 null       || number    | number | number  | number | string | string | 
 boolean    || number    | number | number  | number | string | string | 
 number     || number    | number | number  | number | string | string | 
 string     || string    | string | string  | string | string | string | 
 object     || string    | string | string  | string | string | string | 

* 适用于 Chrome13、FF6、Opera11 和 IE9。检查其他浏览器和版本留给读者作为练习。

注意:正如CMS所指出的,对于对象的某些情况,例如Number,Boolean和自定义对象+运算符不一定会产生字符串结果。它可以根据对象到原始转换的实现而变化。例如var o = { valueOf:function () { return 4; } };评估o + 2;产生6,a number,评估o + '2'产生'42',a string

要查看概览表是如何生成的,请访问http://jsfiddle.net/1obxuc7m/

JavaScript 的+运算符有两个目的:将两个数字相加,或者连接两个字符串。它对数组没有特定的行为,因此它将它们转换为字符串,然后加入它们。

如果要连接两个数组以生成一个新数组,请改用以下.concat方法

[1, 2].concat([3, 4]) // [1, 2, 3, 4]

如果您想有效地将​​一个数组中的所有元素添加到另一个数组,则需要使用.push 方法

var data = [1, 2];

// ES6+:
data.push(...[3, 4]);
// or legacy:
Array.prototype.push.apply(data, [3, 4]);

// data is now [1, 2, 3, 4]

+操作符的行为ECMA-262 5e Section 11.6.1 中定义

11.6.1 加法运算符 ( + )

加法运算符执行字符串连接或数字加法。生产AdditiveExpression : AdditiveExpression + MultiplicativeExpression评估如下:

  1. lref成为评估的结果AdditiveExpression
  2. 我们lvalGetValue(lref)
  3. rref成为评估的结果MultiplicativeExpression
  4. 我们rvalGetValue(rref)
  5. 我们lprimToPrimitive(lval)
  6. 我们rprimToPrimitive(rval)
  7. 如果Type(lprim)String或者Type(rprim)String,那么
    1. 返回作为连接结果的字符串,ToString(lprim)后跟ToString(rprim)
  8. 返回应用加法运算的结果ToNumber(lprim)ToNumber(rprim)请参阅下面的注释 11.6.3。

你可以看到每个操作数都被转换了ToPrimitive通过进一步阅读我们可以发现,ToPrimitive总是将数组转换为字符串,从而产生这样的结果。

您可以使用[].push.apply(data, [3,4])稍微少一点的冗长。此外,这保证可以抵抗其他人更改 的值Array
2021-03-17 16:52:22
这里有一点 tmi,但我同意 schnaader。最好的答案解释了被问到的问题/错误/行为,然后展示了如何产生预期的结果。+1
2021-03-21 16:52:22
为什么要使用更详细的Array.prototype.push.apply(data, [3, 4])而不是data.concat([3,4])
2021-03-28 16:52:22
+1 因为这个答案不仅解释了问题,还解释了如何正确地做。
2021-03-29 16:52:22
@evilcelery:它们有不同的用途。concat产生一个新的数组,更长的调用有效地扩展了一个现有的数组。
2021-04-08 16:52:22

它将两个数组相加,就好像它们是字符串一样

第一个数组的字符串表示是"1,2",第二个是"3,4"因此,当+找到符号,它不能对数组求和然后将它们连接为字符串。

是的,这是第一个出现在脑海中的独特解释,但是,这不是一种非常奇怪的行为吗?也许有一些黑暗的,未知的操作/转换正在进行,我很想知道内部:P
2021-03-31 16:52:22

+concats字符串,因此它的数组转换为字符串。

[1,2] + [3,4]
'1,2' + '3,4'
1,23,4

要组合数组,请使用concat.

[1,2].concat([3,4])
[1,2,3,4]

在 JavaScript 中,二元加法运算符 ( +) 执行数字加法和字符串连接。但是,当它的第一个参数既不是数字也不是字符串时,它会将其转换为字符串(因此是“ 1,2”),然后对第二个“ 3,4执行相同的操作并将它们连接到“ 1,23,4”。

尝试使用数组的“concat”方法:

var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];