【问题标题】:A better way to splice an array into an array in javascript在javascript中将数组拼接成数组的更好方法
【发布时间】:2010-11-23 19:21:56
【问题描述】:

有没有比这更好的方法在javascript中将一个数组拼接到另一个数组中

var string = 'theArray.splice('+start+', '+number+',"'+newItemsArray.join('","')+'");';
eval(string);

【问题讨论】:

  • 作为一般经验法则,在 JavaScript 中应该不惜一切代价避免使用eval。使用eval总是(无一例外)更容易出错、更容易出错、更难调试,并且比替代方法慢得多。如果您想使用eval,请寻求帮助或从头开始重写您的代码。 eval 是 JavaScript 的祸根。我从来没有用过eval。如果我需要执行代码,我会使用更高级的Function。在这种情况下,如果start 是一个字符串,如果number 是一个字符串,或者如果newItemsArray 中的任何字符串包含引号或换行符或回车符,您的代码可能会失败

标签: javascript arrays


【解决方案1】:

您可以使用apply 来避免 eval:

var args = [start, number].concat(newItemsArray);
Array.prototype.splice.apply(theArray, args);

apply 函数用于调用另一个函数,具有给定的上下文和参数,以数组形式提供,例如:

如果我们调用:

var nums = [1,2,3,4];
Math.min.apply(Math, nums);

apply 函数将执行:

Math.min(1,2,3,4);

【讨论】:

  • 虽然,事实证明我需要做 Array.prototype.splice.apply(theArray, [start, number].concat(newItemsArray)) 作为所有参数,而不仅仅是一些,必须在一个数组。
  • +1 表示[start, number].concat(array) 模式。这很漂亮
  • 有没有人试过在Chrome下输入大量元素?大约 130K 元素我们似乎得到了 Stackoverflow 异常。见:jsfiddle.net/DcHCY
  • @Claudiu 另一个巧妙的技巧是将Array.prototype 替换为[]。所以命令可以是:[].splice.apply(theArray, [start, removeCount].concat(newItemsArray);
  • 对 Gabriel Kohen 的回复很晚,但是使用 apply 或 ... 运算符都存在处理大型数据集的问题,您受到特定 JavaScript 引擎的参数限制的限制。
【解决方案2】:

更新:ES6 版本

如果您在 ES6 中编码,您可以使用“扩展运算符”(...)

array.splice(index, 0, ...arrayToInsert);

要了解有关扩展运算符的更多信息,请参阅mozilla documentation

“旧”ES5 方式

如果您将最佳答案包装到一个函数中,您会得到:

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
}

你会这样使用它:

var arr = ["A", "B", "C"];
insertArrayAt(arr, 1, ["x", "y", "z"]);
alert(JSON.stringify(arr)); // output: A, x, y, z, B, C

您可以在这个 jsFiddle 中查看:http://jsfiddle.net/luisperezphd/Wc8aS/

【讨论】:

  • 有趣,没有意识到函数参数被强制转换为数组并且传播语法是有效的
  • array.splice(index, 0, ...arrayToInsert); 的成功之处似乎是迄今为止最流畅的解决方案
【解决方案3】:

如果您想要与 splice 方法几乎相同的东西,您也可以将这样的函数添加到 Array 原型中。例如

Array.prototype.spliceArray = function(index, n, array) {
    return Array.prototype.splice.apply(this, [index, n].concat(array));
}

那么用法就是:

var array = ["A","B","C","","E","F"];

array.splice(3,1,"D");
// array is ["A","B","C","D","E","F"]

array.spliceArray(3,3,["1","2","3"]);
// array is ["A","B","C","1","2","3"]

在此处查看实际操作:http://jsfiddle.net/TheMadDeveloper/knv2f8bb/1/

一些注意事项:

  • splice 函数直接修改数组,但返回的是被移除元素的数组...而不是拼接后的数组。
  • 虽然通常不建议扩展核心 javascript 类,但这对于大多数标准框架来说是相对良性的。
  • 扩展 Array 在使用特殊数组类的情况下不起作用,例如 ImageData 数据 Uint8ClampedArray。

【讨论】:

    【解决方案4】:

    上面涉及 splice.apply 并将数组插入单行的答案将在大型数组的堆栈溢出中炸毁堆栈。 请参见此处的示例: http://jsfiddle.net/gkohen/u49ku99q/ 您可能必须切片并推送原始数组的插入部分和剩余部分的每个项目才能使其工作。 见小提琴:http://jsfiddle.net/gkohen/g9abppgy/26/

    Array.prototype.spliceArray = function(index, insertedArray) {
       var postArray = this.splice(index);
       inPlacePush(this, insertedArray);
       inPlacePush(this, postArray);
    
       function inPlacePush(targetArray, pushedArray) {
    // Not using forEach for browser compatability
           var pushedArrayLength = pushedArray.length;
           for (var index = 0; index < pushedArrayLength; index++) {
               targetArray.push(pushedArray[index]);
           }
       }
    }
    

    【讨论】:

    • 您知道 splice.apply 会出现此问题,还是特定于浏览器?
    • @Drenai,这是每个浏览器的限制,您可以很容易地使用提到的大型数组来达到此限制here
    【解决方案5】:

    我想要一个函数,它只占用源数组的一部分,所以我的略有不同 基于CMS's answer

    function spliceArray(array, index, howmany, source, start, end) {
        var arguments;
      if( source !== undefined ){
        arguments = source.slice(start, end);
        arguments.splice(0,0, index, howmany);
      } else{
       arguments = [index, howmany];
      }
        return Array.prototype.splice.apply(array, arguments)
    }
    
    Array.prototype.spliceArray = function(index, howmany, source, start, end) {
        return spliceArray(this, index, howmany, source, start, end);
    }
    

    您可以在以下位置查看:https://jsfiddle.net/matthewvukomanovic/nx858uz5/

    【讨论】:

      【解决方案6】:

      这个问题真的很老了,但是在 ES6 中,有一种更简单的方法可以使用扩展运算符来做到这一点:

      sourceArray.splice(index, 0, ...insertedArray)
      

      如果您在浏览器中使用未编译的 javascript,请务必检查目标浏览器是否支持 https://kangax.github.io/compat-table/es6/#test-spread_(...)_operator


      另外,这可能有点离题,但如果您不想或不需要修改原始数组,但可以使用新数组,请考虑以下方法:

      mergedArray = sourceArray.slice(0, index).concat(insertedArray, sourceArray.slice(index))
      

      【讨论】:

        【解决方案7】:

        这里有很多聪明的答案,但是您使用 splice 的原因是它可以将元素放入当前数组而不创建另一个数组。如果您必须针对concat() 创建一个数组,以便您可以使用apply(),那么您将创建2 个额外的垃圾数组! Sorta 违背了编写深奥 Javascript 的全部目的。此外,如果你不关心内存使用的东西(你应该)只是dest = src1.concat(src2);它具有无限的可读性。所以这是我保持有效答案的最少行数。

        for( let item of src ) dest.push( item );
        

        或者,如果您想对其进行 polyfill 并获得更好的浏览器支持:

        src.forEach( function( x ) { dest.push(x); });
        

        我确信第一个性能更好(它是一个词;),但并非所有浏览器都支持。

        【讨论】:

          【解决方案8】:

          如果您不想将插入项连接到Array.splice() 的前两个参数, 一种优雅的方式是同时使用Function.bind()Function.apply()

          theArray.splice.bind(null, startIndex, deleteCount).apply(newItemsArray);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-18
            • 1970-01-01
            • 1970-01-01
            • 2014-06-04
            • 1970-01-01
            • 2023-02-08
            • 2011-10-29
            • 1970-01-01
            相关资源
            最近更新 更多