我想将一个数组的元素添加到另一个数组中,所以我尝试了这个:
[1,2] + [3,4]
它做出了回应:
"1,23,4"
发生了什么?
我想将一个数组的元素添加到另一个数组中,所以我尝试了这个:
[1,2] + [3,4]
它做出了回应:
"1,23,4"
发生了什么?
+
运算符不适用于数组。
发生的情况是 Javascript 将数组转换为字符串并连接它们。
由于这个问题及我的回答引起了很多关注,我认为有一个关于+
运算符一般行为的概述也会很有用和相关。
所以,接下来就是它。
除了E4X和特定实现的东西外,Javascript(截至ES5)有6个内置数据类型:
请注意,尽管typeof
有点令人困惑地返回object
用于Null和function
用于可调用对象,但Null实际上不是一个对象,严格来说,在规范符合的Javascript实现中,所有函数都被认为是对象。
没错- Javascript没有原始数组,只有一个名为Array
的对象实例,其中一些语法糖可以减轻痛苦。
为了增加混淆,包装实体比如 new Number(5)
、new Boolean(true)
和 new String("abc")
都是 object
类型,而不是数字、布尔值或字符串,这可能会让人感到意外。但是对于算术运算符来说,Number
和 Boolean
会像数字一样行事。
很简单,对吧?现在我们可以继续进行概述了。
操作数类型不同导致的 +
运算结果类型不同
|| 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
,一个number
,评估o + '2'
会产生'42'
,一个string
。
要了解概述表是如何生成的,请访问http://jsfiddle.net/1obxuc7m/
Date
对象相加会发生什么?typeof new Date()
返回"object"
。根据您的表格,添加结果应该是一个字符串,但事实并非如此。它是一个数字。加法运算符肯定存在更多细节,而不仅仅是表格中所显示的那些。它在每种情况下都无效。 - user15321167typeof(new Date() + new Date())
并按回车键。结果将是 string
,除非您使用的浏览器运行非标准的 JavaScript 实现。该表格是有效的。 - SaulJavaScript的+
运算符有两个用途:将两个数字相加或连接两个字符串。对于数组,它没有特定的行为,因此会将它们转换为字符串,然后连接它们。
如果您想要连接两个数组以生成一个新数组,请使用.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
的求值过程如下:
- 计算
AdditiveExpression
生成引用lref
。- 计算
GetValue(lref)
并将结果赋值给lval
。- 计算
MultiplicativeExpression
生成引用rref
。- 计算
GetValue(rref)
并将结果赋值给rval
。- 将
lval
转换为原始值lprim
。- 将
rval
转换为原始值rprim
。- 如果
Type(lprim)
是字符串或者Type(rprim)
是字符串,那么
- 返回由将
ToString(lprim)
和ToString(rprim)
相连得到的字符串。- 否则,返回将
ToNumber(lprim)
和ToNumber(rprim)
的结果应用于加法运算符的值。参见11.6.3的注释。
可以看到每个操作数都被转换为了原始值(ToPrimitive
)。通过继续阅读,我们可以发现ToPrimitive
总是将数组转换为字符串,从而产生这个结果。
Array.prototype.push.apply(data, [3, 4])
而不是 data.concat([3,4])
? - evilceleryconcat
生成一个新的数组,而更长的调用则有效地扩展了现有的数组。 - Jeremy[].push.apply(data, [3,4])
来减少冗余。此外,这也保证了对于其他人更改Array
的值是有抵抗力的。 - Sam Tobin-Hochstadt它将这两个数组添加为如果它们是字符串。
第一个数组的字符串表示将是"1,2",第二个将是"3,4"。因此,当找到+
符号时,它不能将数组相加,然后将它们连接作为字符串。
+
连接字符串,因此它将数组转换为字符串。
[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];
这是将个别数组转换为字符串,然后将这些字符串合并。
JavaScript中的[1,2] + [3,4]
等价于以下表达式:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
为了解决你的问题,最好的方法是原地添加两个数组,或者不创建新的数组:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
看起来JavaScript将您的数组转换为字符串并将它们连接在一起。如果要将元组相加,则必须使用循环或map函数。
它正在按照您要求的方式执行。
您正在相加的是数组引用(JS会将其转换为字符串),而不是像看起来那样的数字。 这有点像将字符串相加:"hello " + "world"
= "hello world"
[5,6,7][1,2]
的结果是7
,因为它使用了第二个数组中的最后一个元素。O.o - vsync