Самый быстрый способ продублировать массив в JavaScript - слайс против цикла 'for' - PullRequest
556 голосов
/ 20 октября 2010

Для того, чтобы продублировать массив в JavaScript: что из следующего быстрее использовать?

Метод среза

var dup_array = original_array.slice();

For петля

for(var i = 0, len = original_array.length; i < len; ++i)
   dup_array[i] = original_array[i];

Я знаю, что оба способа делают только поверхностную копию : если original_array содержит ссылки на объекты, объекты не будут клонированы, а будут скопированы только ссылки, и поэтому оба массива будут иметь ссылки на одни и те же объекты. Но суть этого вопроса не в этом.

Я спрашиваю только о скорости.

Ответы [ 17 ]

712 голосов
/ 12 декабря 2013

Существует как минимум 5 (!) Способов клонирования массива:

  • петли
  • ломтик
  • Array.from ()
  • CONCAT
  • оператор распространения (FASTEST)

Произошло huuuge поток ЭТАЛОНОВ , предоставляющий следующую информацию:

  • для мигает браузеры slice() - самый быстрый метод, concat() немного медленнее, а while loop - в 2,4 раза медленнее.

  • для других браузеров while loop - самый быстрый метод, так как эти браузеры не имеют внутренних оптимизаций для slice и concat.

Это остается верным в июле 2016 года.

Ниже приведены простые сценарии, которые вы можете скопировать и вставить в консоль вашего браузера и запустить несколько раз, чтобы увидеть картинку. Они выводят миллисекунды, чем меньше, тем лучше.

в то время как цикл

n = 1000*1000;
start = + new Date();
a = Array(n); 
b = Array(n); 
i = a.length;
while(i--) b[i] = a[i];
console.log(new Date() - start);

ломтик

n = 1000*1000;
start = + new Date();
a = Array(n); 
b = a.slice();
console.log(new Date() - start);

Обратите внимание, что эти методы клонируют сам объект Array, однако содержимое массива копируется по ссылке и не клонируется глубоко.

origAr == clonedArr //returns false
origAr[0] == clonedArr[0] //returns true
209 голосов
/ 02 февраля 2014

Технически slice - это самый быстрый способ. Однако , это даже быстрее, если вы добавите 0 начало индекса.

myArray.slice(0);

быстрее

myArray.slice();

http://jsperf.com/cloning-arrays/3

116 голосов
/ 06 июля 2015

а как насчет es6?

arr2 = [...arr1];
41 голосов
/ 06 мая 2014

Самый простой способ глубокого клонирования массива или объекта:

var dup_array = JSON.parse(JSON.stringify(original_array))
27 голосов
/ 05 октября 2016
var cloned_array = [].concat(target_array);
25 голосов
/ 20 октября 2010

Я собрал быструю демонстрацию: http://jsbin.com/agugo3/edit

Мои результаты в Internet Explorer 8 - 156, 782 и 750, что указывает на то, что slice намного быстрее в этом случае.

19 голосов
/ 29 мая 2016

a.map(e => e) является еще одной альтернативой для этой работы.На сегодняшний день .map() очень быстро (почти так же быстро, как .slice(0)) в Firefox, но не в Chrome.

С другой стороны, если массив является многомерным, так как массивы являются объектами иобъекты являются ссылочными типами, ни один из методов slice или concat не излечит ... Итак, один правильный способ клонирования массива - это выдумка Array.prototype.clone() следующим образом.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var arr = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 , 5], 6 ],
    brr = arr.clone();
brr[4][2][1] = "two";
console.log(JSON.stringify(arr));
console.log(JSON.stringify(brr));
11 голосов
/ 22 октября 2018

Самый быстрый способ клонирования массива

Я сделал эту очень простую служебную функцию, чтобы проверить время, необходимое для клонирования массива.Он не на 100% надежен, однако он может дать вам общее представление о том, сколько времени потребуется для клонирования существующего массива:

function clone(fn) {
    const arr = [...Array(1000000)];
    console.time('timer');
    fn(arr);
    console.timeEnd('timer');
}

И протестировал другой подход:

1)   5.79ms -> clone(arr => Object.values(arr));
2)   7.23ms -> clone(arr => [].concat(arr));
3)   9.13ms -> clone(arr => arr.slice());
4)  24.04ms -> clone(arr => { const a = []; for (let val of arr) { a.push(val); } return a; });
5)  30.02ms -> clone(arr => [...arr]);
6)  39.72ms -> clone(arr => JSON.parse(JSON.stringify(arr)));
7)  99.80ms -> clone(arr => arr.map(i => i));
8) 259.29ms -> clone(arr => Object.assign([], arr));
9) Maximum call stack size exceeded -> clone(arr => Array.of(...arr));

UPDATE :Примечание: из всех них единственным способом глубокого клонирования массива является использование JSON.parse(JSON.stringify(arr)).Тем не менее, не используйте вышеприведенное, если ваш массив может содержать функции, так как он вернет null. Спасибо @GilEpshtain за это обновление .

7 голосов
/ 20 октября 2010

Зависит от браузера. Если вы посмотрите в блоге Array.prototype.slice или ручное создание массива , то есть приблизительное руководство по производительности каждого из них:

Enter image description here

Результаты:

Enter image description here

6 голосов
/ 21 января 2016

Помните, что .slice () не будет работать для двумерных массивов.Вам понадобится такая функция:

function copy(array) {
  return array.map(function(arr) {
    return arr.slice();
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...