为啥 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中?
Posted
技术标签:
【中文标题】为啥 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中?【英文标题】:Why is [1,2] + [3,4] = "1,23,4" in JavaScript?为什么 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中? 【发布时间】:2011-10-30 19:01:56 【问题描述】:我想将一个数组的元素添加到另一个数组中,所以我尝试了这个:
[1,2] + [3,4]
它的回应是:
"1,23,4"
发生了什么事?
【问题讨论】:
这里有一个与此主题相关的问题:***.com/questions/1724255/why-does-2-2-in-javascript 啊哈哈,虐待狂面试官甚至可以问这样的问题 - 这将返回 [1,2] + [5,6,7][1,2]。为什么? 我认为 [1,2] + [3,4] 是本周 firebug 中评估最多的表达式,仅次于 alert('crap')。 想笑吗?尝试 [] + []、 + []、 + 和 [] + @shabunc - 解释一下为什么[5,6,7][1,2]
是7
,因为它使用了第二个数组中的最后一项。 O.o
【参考方案1】:
这里的一些答案已经解释了意外的不想要的输出 ('1,23,4'
) 是如何发生的,有些答案已经解释了如何获得他们认为是预期的期望输出 ([1,2,3,4]
),即数组连接。然而,预期的期望输出的性质实际上有点模棱两可,因为最初的问题只是简单地说“我想将一个数组的元素添加到另一个......”。 可以表示数组连接,但也表示元组加法(例如here和here),即将一个数组中元素的标量值添加到标量第二个中相应元素的值,例如结合[1,2]
和[3,4]
得到[4,6]
。
假设两个数组具有相同的数量/长度,这是一个简单的解决方案:
const arr1 = [1, 2];
const arr2 = [3, 4];
const add = (a1, a2) => a1.map((e, i) => e + a2[i]);
console.log(add(arr1, arr2)); // ==> [4, 6]
【讨论】:
【参考方案2】:JavaScript 的+
运算符有两个用途:添加两个数字,或连接两个字符串。它对数组没有特定的行为,所以它将它们转换为字符串然后加入它们。
如果您想连接两个数组以生成一个新数组,请改用the .concat
method:
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
如果你想高效地将一个数组中的所有元素添加到另一个数组中,你需要使用the .push method:
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
评估如下:让
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)
的结果ToNumber(lprim)
和ToNumber(rprim)
。请参阅下面 11.6.3 的注释。
您可以看到每个操作数都转换为ToPrimitive
。通过进一步阅读我们可以发现ToPrimitive
总是会将数组转换为字符串,从而产生这个结果。
【讨论】:
+1 因为这个答案不仅解释了问题,还解释了如何正确地做。 这里有一点tmi,但我同意schnaader。最佳答案解释了所询问的问题/错误/行为,然后显示了如何产生预期的结果。 +1 为什么要使用更详细的Array.prototype.push.apply(data, [3, 4])
而不是data.concat([3,4])
?
@evilcelery:它们有不同的用途。 concat
产生一个 new 数组,更长的调用有效地扩展了一个 existing 数组。
您可以使用[].push.apply(data, [3,4])
来减少冗长。此外,这可以保证防止其他人更改 Array
的值。【参考方案3】:
+
运算符没有为数组定义。
发生的是 Javascript 将数组转换为字符串并将它们连接起来。
更新
由于这个问题以及因此我的回答引起了很多关注,我觉得对+
运算符的一般行为方式进行概述会很有用且相关。
所以,就这样吧。
不包括 E4X 和特定于实现的东西,Javascript(从 ES5 开始)有 6 内置 data types:
-
未定义
空
布尔值
号码
字符串
对象
请注意,尽管typeof
somewhat confusingly returns object
用于 Null,function
用于可调用对象,但 Null 实际上不是对象,严格来说,在符合规范的 Javascript 实现中,所有函数都被视为对象。
没错 - Javascript 本身就没有原始数组;只有一个名为 Array
的 Object 实例,并带有一些语法糖以减轻痛苦。
更令人困惑的是,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/
【讨论】:
【参考方案4】:仅使用简单的“+”号的另一个结果是:
[1,2]+','+[3,4] === [1,2,3,4]
所以这样的事情应该可以工作(但是!):
var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]
... 但它会将变量 a 从数组转换为字符串!记住这一点。
【讨论】:
【参考方案5】:这是因为,+ 运算符假定操作数是字符串,如果它们不是数字的话。因此,如果它不是数字,它首先将它们转换为字符串并连接以给出最终结果。另外,它不支持数组。
【讨论】:
+ 运算符不能假定操作数是字符串,因为 1 + 1 == 2 等等。这是因为没有为数组定义'+',所以它对它们进行String-s。【参考方案6】: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);
【讨论】:
【参考方案7】:如果您可以在 JavaScript 中重载运算符但您不能: Can I define custom operator overloads in Javascript? 您只能破解在比较之前转换为字符串的“==”运算符: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
【讨论】:
【参考方案8】:它将两个数组添加为字符串。
第一个数组的字符串表示为 "1,2",第二个数组表示为 "3,4"。因此,当找到+
符号时,它不能对数组求和然后将它们连接为字符串。
【讨论】:
是的,这是脑海中第一个独特的解释,但是,这不是很奇怪的行为吗?也许正在进行一些黑暗的、未知的操作/改造,我很想知道内部情况:P【参考方案9】:在 JavaScript 中,二进制加法运算符 (+
) 执行数字加法和字符串连接。但是,当它的第一个参数既不是数字也不是字符串时,它会将其转换为字符串(因此为“1,2
”),然后它对第二个“3,4
”执行相同操作并将它们连接到“1,23,4
” .
尝试使用数组的“concat”方法:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
【讨论】:
【参考方案10】:+
连接字符串,因此它将数组转换为字符串。
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
要组合数组,请使用concat
。
[1,2].concat([3,4])
[1,2,3,4]
【讨论】:
【参考方案11】:它将单个数组转换为字符串,然后组合字符串。
【讨论】:
【参考方案12】:看起来 JavaScript 正在将您的数组转换为字符串并将它们连接在一起。如果要将元组添加在一起,则必须使用循环或映射函数。
【讨论】:
【参考方案13】:它正在做你要求它做的事情。
您要添加的是数组引用(JS 将其转换为字符串),而不是看起来的数字。这有点像将字符串加在一起:"hello " + "world"
= "hello world"
【讨论】:
呵呵,它总是按我的要求做。问题是提出好的问题。让我感兴趣的是添加数组时对数组的 toString() 解释。以上是关于为啥 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 1+ +"2"+3 在 JavaScript 中计算为 6? [复制]
python 的range()函数怎么使用,为啥单独运行print(range(1,5))输出还是range(1,5),而不是[1,2,3,4]
Java中的Set类差集问题?差集为啥是1,2不是1,2,8,9,;