Самый быстрый способ дублирования массива в JavaScript: slice против цикла 'for'
Вопрос: Какой из следующих способов дублирования массива в JavaScript быстрее?
- Метод
slice
:
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
содержит ссылки на объекты, то объекты не будут клонированы, а только ссылки будут скопированы, из-за чего оба массива будут ссылаться на одни и те же объекты. Но это не суть моего вопроса.
Я спрашиваю только о производительности. Какой метод будет быстрее?
5 ответ(ов)
С точки зрения производительности, slice
действительно является самым быстрым способом. Тем не менее, он работает еще быстрее, если вы укажете индекс начала равным 0
.
Пример:
myArray.slice(0);
работает быстрее, чем
myArray.slice();
Вы можете проверить это по ссылке: https://jsben.ch/F0SZ3.
В контексте ES6 (или ECMAScript 2015), более современный способ создать копию массива — это использовать оператор расширения (spread operator). Вот как это можно сделать:
arr2 = [...arr1];
Этот синтаксис создает новый массив arr2
, который является копией массива arr1
. Оператор ...
развертывает элементы arr1
и добавляет их в новый массив arr2
. Это удобно, так как такой способ легко читается и не требует использования методов вроде Array.prototype.slice()
, что делает код более лаконичным и ясным.
Самый простой способ глубокого клонирования массива или объекта в JavaScript — это использовать метод JSON.parse
вместе с JSON.stringify
. Вот пример:
var dup_array = JSON.parse(JSON.stringify(original_array));
Этот подход работает, поскольку преобразует объект или массив в строку JSON, а затем распарсит его обратно в новый объект или массив, тем самым создавая глубокую копию. Однако имейте в виду, что этот метод не работает с элементами, которые не могут быть сериализованы в JSON, такими как функции, специальные объекты (например, Date
, Map
, Set
и т.д.) или циклические ссылки. Если вам нужно учесть такие случаи, рассмотрите использование библиотек, таких как Lodash с методом _.cloneDeep()
.
🏁 Самый быстрый способ клонирования массива
Я создал эту простую утилитарную функцию, чтобы протестировать время, которое требуется для клонирования массива. Она не является на 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) Превышен максимальный размер стека вызовов -> clone(arr => Array.of(...arr));
ОБНОВЛЕНИЯ
- Тесты были проведены в 2018 году, поэтому результаты могут отличаться в современных браузерах.
- Из этих методов лучший способ глубокого клонирования массива — использование
JSON.parse(JSON.stringify(arr))
. - Не используйте данный способ, если ваш массив может содержать функции, так как он вернет
null
. Спасибо @GilEpshtain за это обновление.
Для создания "клированного" массива в JavaScript, можно использовать метод concat()
, как показано в следующем примере:
var cloned_array = [].concat(target_array);
Этот код создает новый массив cloned_array
, который является поверхностной копией массива target_array
. Метод concat()
объединяет массивы, но если передать в качестве аргумента пустой массив ([]
), он просто вернет копию указанного массива. Учтите, что это метод создает лишь поверхностную копию; если в target_array
есть вложенные объекты, они будут скопированы по ссылке, а не по значению.
Как получить первые N элементов массива
Как удалить все дубликаты из массива объектов?
Удалить последний элемент из массива
Как объединить два массива в JavaScript и удалить дубликаты?
Как проверить, пустой ли массив или он не существует?