由于这里似乎对各种数组附加方法的使用存在普遍的误解,我将用 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 可以。因此,您必须检查 myArray 或 data 是否为当前 JS 版本的正确类型。
参数具有依赖于当前 JS 上下文的限制,JS 上下文对长参数列表的处理也存在不一致。有些会抛出错误,有些会简单地截断参数。
var myPixelData = [];
myPixelData.push.apply(myPixelData,getSomePixelData()); // what will happen????
这可能会抛出,或者它可能会起作用,或者它可能只将 65535 个项目推送到数组中,或者更多,或者更少。您必须将其包装在 try catch 中,并根据 getPixelData 返回的数组长度检查结果。所有增加的复杂性只是为了让它更容易???
那么为什么要在Array.push 上使用Function.apply 或使用Array.concat,因为编写一个函数来做你想做的事情要容易得多,并且可以让你免于一长串的问题、歧义和错误。