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

2022-08-29 23:23:20

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

[1,2] + [3,4]

它的回应是:

"1,23,4"

这是怎么回事?


答案 1

未为数组定义运算符。+

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

 

更新

由于这个问题以及我的答案得到了很多关注,我认为对操作员的一般行为进行概述也是有用且相关的。+

所以,它开始了。

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

  1. 定义
  2. 布尔
  3. 字符串
  4. 对象

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

没错 - Javascript没有原始数组;只有对象的实例用一些句法糖调用以减轻疼痛。Array

更令人困惑的是,包装实体(如 )和所有类型,而不是人们可能期望的数字,布尔值或字符串。然而,对于算术运算符和表现为数字。new Number(5)new Boolean(true)new String("abc")objectNumberBoolean

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

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

            || 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 所指出的,对于对象(如 和 自定义对象)的某些情况,运算符不一定生成字符串结果。它可能因对象到基元转换的实现而异。例如,计算产生 ,a ,计算产生,a 。NumberBoolean+var o = { valueOf:function () { return 4; } };o + 2;6numbero + '2''42'string

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


答案 2

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 第 11.6.1 节中定义了操作员的行为:+

11.6.1 加法运算符 ( + )

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

  1. 让我们成为评估的结果。lrefAdditiveExpression
  2. 听任。lvalGetValue(lref)
  3. 让我们成为评估的结果。rrefMultiplicativeExpression
  4. 听任。rvalGetValue(rref)
  5. 听任。lprimToPrimitive(lval)
  6. 听任。rprimToPrimitive(rval)
  7. 如果 是 或 是 ,则Type(lprim)StringType(rprim)String
    1. 返回字符串,该字符串是串联的结果,后跟ToString(lprim)ToString(rprim)
  8. 返回对 和 应用加法运算的结果。请参阅下面的注释 11.6.3。ToNumber(lprim)ToNumber(rprim)

您可以看到每个操作数都已转换。通过进一步阅读,我们可以发现它将始终将数组转换为字符串,从而产生此结果。ToPrimitiveToPrimitive