[1,2,3,4,5].duplicate(); // [1,2,3,4,5,1,2,3,4,5]
也许可以这样做:
var array = [1,2,3,4,5];
array.push(array);
但是什么是最快的方法?
[1,2,3,4,5].duplicate(); // [1,2,3,4,5,1,2,3,4,5]
var array = [1,2,3,4,5];
array.push(array);
var array = [1,2,3]; array = array.concat(array);
返回 [1, 2, 3, 1, 2, 3]
。 - Oriolarray.concat(array);
即可完成与array = array.concat(array);
相同的操作。 - Magicprog.frconcat
不会改变原始数组,所以我用新的数组替换它。push
会修改原始数组。 - Oriol在JS中,最快的做某件事情的方法通常是使用类似于C语言的本地语句。
我认为这将是最快的方法:
function duplicate(arr) {
for(var i=0,len=arr.length;i<len;i++)
arr[i+len]=arr[i];
}
arr=arr.concat(arr);
[].push.apply(arr,arr);
EcmaScript 6 还允许您使用展开运算符来完成同样的操作。该运算符会将数组中的所有值放置在您编写的位置,因此这个代码 var arr = [0,1,2,3];console.log(...arr)
可以转换成var arr = [0,1,2,3];console.log(0,1,2,3)
。
arr.push(...arr);
EcmaScript-262第6版于5天前正式发布(感谢@LyeFish)! http://www.ecma-international.org/news/index.html
concat
方法和push
方法。我还测试了循环方法和我自己新引入的splice
例程。var toArray = Function.prototype.call.bind(Array.prototype.slice);
Function.prototype.testerTimes = function(number) {
var func = this;
return function() {
var args = toArray(arguments), i = 0;
for( ; i < number; func.apply(this, args), i++);
};
};
Function.prototype.testerTime = function(units) {
var func = this;
return function() {
var start = Date.now(), diff;
func.apply(this, toArray(arguments));
diff = Date.now() - start;
return units === "s" ? diff / 1000 : units === "m" ? diff / 60000 : units === "h" ? diff / 3600000 : diff;
};
};
Function.prototype.testerToConsole = function(prefix, message) {
var func = this;
return function() {
console.log(prefix + message + func.apply(this, toArray(arguments)));
};
};
Function.prototype.makeTestReady = function(times, units, prefix, message) {
return this.testerTimes(times).testerTime(units).testerToConsole(prefix, message);
};
function genArray(num) {
for(var i = 0, arr = []; i < num; arr.push(++i));
return arr;
};
var numberOfRuns = 1000000;
var timeUnit = "s";
var messagePrefix = " ";
var funcs = [
function duplicateConcat(arr) {
var arrCopy = arr.slice(0);
return arrCopy.concat(arrCopy);
},
function duplicatePush(arr) {
var arrCopy = arr.slice(0);
arrCopy.push.apply(arrCopy, arrCopy);
return arrCopy;
},
function duplicateLoop(arr) {
var arrCopy = arr.slice(0);
for(var i = 0, len = arrCopy.length; i < len; i++) {
arrCopy[len + i] = arrCopy[i];
}
return arrCopy;
},
function duplicateSplice(arr) {
var arrCopy = arr.slice(0);
arrCopy.splice.apply(arrCopy, [arrCopy.length, 0].concat(arrCopy));
return arrCopy;
}
].map(function(func, index, arr) {
return func.makeTestReady(numberOfRuns, timeUnit, messagePrefix, func.name + ": ");
});
for(var i = 5; i < 25; i+= 5) {
console.log(i + "-element array:");
funcs.forEach(function(func) {
func(genArray(i));
});
}
这里是每个函数在数组大小为5、10、15和20的情况下运行100万次的结果:
5-element array:
duplicateConcat: 0.236
duplicatePush: 0.228
duplicateLoop: 0.372
duplicateSplice: 0.45
10-element array:
duplicateConcat: 0.241
duplicatePush: 0.273
duplicateLoop: 0.433
duplicateSplice: 0.48
15-element array:
duplicateConcat: 0.261
duplicatePush: 0.293
duplicateLoop: 0.5
duplicateSplice: 0.522
20-element array:
duplicateConcat: 0.24
duplicatePush: 0.311
duplicateLoop: 0.602
duplicateSplice: 0.558
.apply()
时,执行toArray(arguments)
是不必要的。自ECMAScript 3以来,.apply()
方法已被指定为接受本地数组和参数对象。ECMAScript 5随后扩展了其定义。话虽如此...比较.concat()
和.push.apply
似乎有点毫无意义,因为它们执行两个不同的操作。没有人会执行array.slice(0)
,然后再执行.push.apply
,因为单个.concat()
将具有相同的效果。 - user1106925toArray()
函数是基于向后兼容的目的使用的,以防某些人使用旧版本浏览器或旧版本的 node。在 push
版本中,arr.slice(0)
语句是必要的,因为否则数组会不断增长并且你会溢出堆栈。arr.slice(0)
语句被添加到每个函数中,以确保它们等效,除了它们自己独特的复制实现。这是为了确保性能指标没有偏见而做的。 - DRDarr.slice(0)
。我只是想说,即使没有它,比较这两种方法也是在比较两个不同的东西(而不是对同一件事情的不同方法)。至于旧浏览器,你需要使用类似 IE5 的浏览器才会出现兼容性问题。如果 SO 甚至能够渲染,我会感到惊讶。 - user1106925concat
返回一个新数组,而push
将元素添加到现有数组中。哪种方法更有效地将一个数组复制到“自身”?时间方面,连接略快一些。 - DRD.concat()
,因此它的性能优势就不再相关。而如果不想改变原始值,那么就永远不会使用.push.apply()
。 - user1106925