【问题标题】: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"

发生了什么事?

【问题讨论】:

  • 这里有一个与此主题相关的问题:stackoverflow.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

标签: javascript arrays string concatenation


【解决方案1】:

这里的一些答案已经解释了意外的不想要的输出 ('1,23,4') 是如何发生的,有些答案已经解释了如何获得他们认为是预期的期望输出 ([1,2,3,4]),即数组连接。然而,预期的期望输出的性质实际上有点模棱两可,因为最初的问题只是简单地说“我想将一个数组的元素添加到另一个......”。 可以表示数组连接,但表示元组加法(例如herehere),即将一个数组中元素的标量值添加到标量第二个中相应元素的值,例如结合[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 评估如下:

    1. lref 成为评估AdditiveExpression 的结果。
    2. lval 成为GetValue(lref)
    3. rref 成为评估MultiplicativeExpression 的结果。
    4. rval 成为GetValue(rref)
    5. lprim 成为ToPrimitive(lval)
    6. rprim 成为ToPrimitive(rval)
    7. 如果Type(lprim)StringType(rprim)String,那么
      1. 返回字符串,它是连接ToString(lprim) 后跟ToString(rprim) 的结果
    8. 将加法运算的结果返回到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:

    1. 未定义
    2. 布尔值
    3. 号码
    4. 字符串
    5. 对象

    请注意,尽管typeof somewhat confusingly returns object 用于 Null,function 用于可调用对象,但 Null 实际上不是对象,严格来说,在符合规范的 Javascript 实现中,所有函数都被视为对象。

    没错 - 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 所指出的,对于NumberBoolean 和自定义对象等特定情况,+ 运算符不一定会产生字符串结果.它可以根据对象到原始转换的实现而有所不同。例如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() 解释。
                    猜你喜欢
                    • 1970-01-01
                    • 2016-05-19
                    • 2020-10-15
                    • 2011-11-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-07-25
                    相关资源
                    最近更新 更多