【问题标题】:how can I concatenate two arrays in javascript?如何在javascript中连接两个数组?
【发布时间】:2016-05-02 19:03:05
【问题描述】:

我看到response 用另一个数组扩展一个数组 所以我尝试了:

console.log(['a', 'b'].push.apply(['c', 'd']));

但它会打印:

2

不应该打印吗:

['a', 'b', 'c', 'd']

如果不是我做错了什么?

【问题讨论】:

标签: javascript arrays concatenation


【解决方案1】:

如果不是我做错了什么?

首先.push返回数组的新长度

var arr = [1, 1, 1];
console.log(arr.push(1)); // 4
console.log(arr); // [1, 1, 1, 1]

其次,.apply 需要两个参数:要应用函数的对象和参数数组。你只传递一个参数,所以你的代码基本上相当于:

['c', 'd'].push()

即您没有向 ['c', 'd'] 数组添加任何内容。这也解释了为什么您在输出中看到2['c', 'd'] 的长度为2,而.push() 没有向其中添加任何元素,因此它的长度仍然为2

如果你想使用.push 来改变原始数组(而不是像.concat 那样创建一个新数组),它必须看起来像:

var arr = ['a', 'b'];
arr.push.apply(arr, ['c', 'd']); // equivalent to Array.prototype.push.apply(arr, [...])
//              ^   ^--------^
//    apply to arr   arguments
console.log(arr); // ['a', 'b', 'c', 'd']

另见

【讨论】:

  • 也许这个例子更清楚:[].push.apply(arr, ['c', 'd']);
  • 我同意,但是,我不喜欢不必要地创建数组;)
【解决方案2】:

试试这个:

 console.log(['a', 'b'].concat(['c', 'd']));

【讨论】:

    【解决方案3】:

    如果您的场景允许使用 ES6 语法,您可以使用 spread element 连接数组:

    var arr1 = [1,2];
    var arr2 = [3,4];
    var arr3 = [...arr1, ...arr2];
    console.log(arr3); // Logs [1,2,3,4]
    

    【讨论】:

    • 我们可以称之为扩展元素吗?它不是运算符(即使您在某些地方阅读过此内容)。
    • 更新为状态spread element。对于任何感兴趣的人,Spread Element 是 ES6 规范中使用的措辞。您可以在Expressions section 中查看。向下滚动一点到 SpreadElement。你知道的越多!
    【解决方案4】:

    如果您使用的是现代浏览器,则可以使用扩展运算符 ...,如下所示:

    console.log([...['a', 'b'], ...['c', 'd']])
    

    如果您使用的是旧版浏览器/没有转译器,那么concat 是您的最佳选择:

    console.log(['a', 'b'].concat(['c', 'd']))
    

    【讨论】:

      【解决方案5】:

      由于这里似乎对各种数组附加方法的使用存在普遍的误解,我将用 ES6 引入扩展运算符的最安全替代方法来添加它

      功能性语言

      开发函数式语言是为了简化代码开发,允许程序员和系统工程师定义函数来替换常见的操作/算法。 JS 是一种函数式语言,你编写函数是为了让生活更轻松,节省你的打字时间,并使程序更容易测试和验证,所以为什么要与危险的替代品抗争呢。

      答案中出现的错误(除了 Jonathan Michalik 的答案)是他们都试图强迫语言做一些应该由函数完成的事情(Function.apply),或者提供一个没有解释它在做什么 (Array.concat)。

      例如,编写一个附加数组的函数。

      function appendArray(array,array1){ // adds the items in array1 
                                          // array1 can be any type
                                          // to the end of array 
          var len,i;
          array1 = [].concat(array1);   // ensure array1 is an array
          len = array1.length;
          i = 0;
          while(i < len){
              array[array.length] = array1[i++]; // this is 2* quicker than invoking push
          }
          return array;
      }
      

      在写入所需的 60 秒内,或者将其包含为通用库的一部分,您已经创建了一个安全且通用的数组附加函数。

      log(appendArray([0, 1, 2, 3], 4)); // 0,1,2,3,4
      log(appendArray([0, 1, 2, 3], [4, 5, 6])); // 0,1,2,3,4,5,6
      

      现在为什么其他答案不是好的解决方案。

      Array.concat

      是更安全的选项,如果您可以控制对数组的所有引用,则应使用该选项。它的缺点是它在使用时会创建一个新数组。

      var array1 = [1,2,3];
      var array2 = [4,5,6];
      array1 = array1.concat(array2); // 1,2,3,4,5,6
      

      许多人错误地认为 concat(array2) 被添加到 array1,它不是,它被添加到 array1 的副本。如果您对原始数组有其他引用,那么您最终会创建串联数组的副本,而原始数组仍保留在内存中。

      function doSomething(array){
          ... generate some info
          array.concat(info);
      }
      
      var myArray = [...someData];  // the array
      var myObject.setArray(myArray); // create a new referance to the array in myObject
      myArray = doSomething(myArray);  // adds info via concat to the array.
      

      这不是很明显,但是您现在有两个数组,原始在 myObject 中,而在 myObject 中的串联版本可以将数组引用存储在闭包中,除非您取消引用所有关联的上下文,否则您无法更改或删除.也不知道有多少对原始数组的引用。

      Function.apply()

      不使用此函数的原因有很多,但需要特别注意的是在Array.push 函数中使用它。如果您在不检查数组的情况下使用它,则会出现不确定性。

      var myArray = [1,2,3,4];
      var data = getSomeData(); // may return array or array like data
      myArray = doSomeWorkOn(myArray); // the spec says this may return undefined
      myArray.push.apply(myArray,data); // what happen here is indeterminate and
                                           // depends on the JS context, the JS mode
                                           // and the JS version
      

      如果不审查 myArray 是否为 undefined,您无法预测 apply 的结果。它可能会抛出错误,或者如果全局范围具有推送功能并且您未处于严格模式,它可能会静默失败。

      在不知道 JS 版本 ES5 或 ES6 的情况下,apply 可能已将一个对象 data 推送到 myArray 上,或者 data 中的所有项目 ES5 无法将类似数组的对象识别为 Function.apply 的数组,而 ES6 可以。因此,您必须检查 myArraydata 是否为当前 JS 版本的正确类型。

      参数具有依赖于当前 JS 上下文的限制,JS 上下文对长参数列表的处理也存在不一致。有些会抛出错误,有些会简单地截断参数。

      var myPixelData = [];
      myPixelData.push.apply(myPixelData,getSomePixelData()); // what will happen????
      

      这可能会抛出,或者它可能会起作用,或者它可能只将 65535 个项目推送到数组中,或者更多,或者更少。您必须将其包装在 try catch 中,并根据 getPixelData 返回的数组长度检查结果。所有增加的复杂性只是为了让它更容易???

      那么为什么要在Array.push 上使用Function.apply 或使用Array.concat,因为编写一个函数来做你想做的事情要容易得多,并且可以让你免于一长串的问题、歧义和错误。

      【讨论】:

        【解决方案6】:

        你应该试试这个:

        a= ['a', 'b'];
        b= ['c', 'd'];
        a.push.apply(a,b);
        
        console.log(a);
        

        【讨论】:

          【解决方案7】:

          你应该像这样使用变量

          	<script type="text/javascript">
          	var arr1=['a', 'b'];
          	var arr2=['c', 'd'];
          	Array.prototype.push.apply(arr1, arr2);
          	 console.log(arr1);
          	</script>

          【讨论】:

          • 这是一个 hacky 解决方案
          • @Matías:你为什么这么认为?
          • 因为有比调用原型函数更好的解决方案...查看其他答案以获取更多详细信息
          • @MatíasFidemraizer:在什么方面“更好”?仅仅因为有“更好”的解决方案并不意味着这个解决方案很老套。你一直在调用原型函数! Array.prototype.push[].push 是同一个功能。
          • Apply 仅应在您希望更改函数调用的 this 值时使用。如果您不检查第一个参数是否为 null 或 undefined 如果您不使用严格模式,那么您只是在堆栈上添加一个加法调用并没有任何好处,并且还会冒污染全局对象的风险。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-09
          • 2010-12-14
          • 2020-02-24
          • 2020-02-05
          • 1970-01-01
          相关资源
          最近更新 更多