Синтаксис спреда и метод среза
Я пытался понять, в чем разница между синтаксисом распространения и методом среза в следующем подходе.
Предположим, что я хочу сделать фактическую копию массива, я могу легко сделать это, используя распространенный синтаксис
var fruits = ["Banana", "Chips" , "Orange", "Lemon", "Apple", "Mango"]
var newCitrus = [...fruits]
Если я console.log это
["Banana", "Chips", "Orange", "Lemon", "Apple", "Mango"]
но я также могу создать копию массива, используя метод среза. Учитывая тот же массив выше, если я сделаю что-то вроде этого...
var citrus = fruits.slice(0);
а затем консоль лог это, он даст мне точно такой же массив, который я получил бы через распространяемый синтаксис
["Banana", "Chips", "Orange", "Lemon", "Apple", "Mango"]
Поскольку на кодирование/запись им обоим требуется примерно одинаковое время, в чем здесь разница? какой подход я обычно выбираю?
Ответы
Ответ 1
Помимо производительности slice
- это просто функция в Array.prototype
, поэтому она будет работать только для массивов. С другой стороны, распространяемый синтаксис будет работать для любого итерируемого (объекта, который удовлетворяет итерируемый протокол), поэтому он будет работать "из коробки" на любых String
, Array
, TypedArray
, Map
и Set
. Вы также можете легко создавать собственные итерации.
Существует также разница в том, что касается slice
и spread
массивов с отверстиями (разреженных массивов). Как вы можете видеть ниже, slice
сохранит разреженность, в то время как spread
заполнит отверстия undefined
.
Array(3) // produces sparse array: [empty × 3]
Array(3).slice() // produces [empty × 3]
[...Array(3)] // produces [undefined, undefined, undefined]
Синтаксис распространения также можно использовать для создания мелких клонов объектов:
const obj = { foo: 'bar', baz: 42 };
const clone = { ...obj1 };
obj.foo === clone.foo // true
obj.baz === clone.baz // true
obj === clone // false (references are different)
Ответ 2
Здесь есть фантастическое объяснение - https://gist.github.com/RubaXa/62743b5e142f9f13a7de; Посмотрите, как он живет здесь - http://jsbench.github.io/#62743b5e142f9f13a7de
в общем случае оператор расширения в два раза быстрее по сравнению с срезом.
Ответ 3
Измерения в Chrome показывают, что срез гораздо более производительный, чем оператор распространения: 67 миллионов операций в секунду против 4 миллионов операций в секунду. Если вы создаете приложение для Chrome или приложения Electron (в котором используется Chromium), я бы предпочел слайс, особенно для приложений с большими данными и в реальном времени.
![Measure results]()
EDIT:
Кажется, что оператор Spread теперь намного быстрее, хотя все еще медленнее, чем Slice:
![Newer Measurement Results]()
Ответ 4
Новые версии Chrome (72+), по-видимому, устранили разрыв в производительности. https://measurethat.net/Benchmarks/ListResults/2667
Ответ 5
Эти два метода на самом деле не эквивалентны. Slice является функцией в Array.prototype
и знает о реализации массивов. Это создаст очень эффективную глубокую копию. Что еще более важно, .slice()
сохранит информацию о редкости вашего массива.
Напротив, [...Array]
просто создаст новый массив из итеративного представления вашего существующего массива. Не обязательно так эффективно.
Попробуйте это:
var a = [];
a.length = 3;
console.log("slice:", a.slice());
console.log("spread:", [...a]);
Благодаря консоли разработчика Chrome Browser я получаю следующие результаты:
slice: (3) [empty × 3]
spread: (3) [undefined, undefined, undefined]
Если ваш массив особенно большой + разреженный, array.slice()
будет исключительно быстрым. [...array]
возможно повесит ваш браузер.
Ответ 6
Производительность будет зависеть от двигателя, на котором он работает. И, как и в большинстве Javscript-кода, он, вероятно, будет работать в различных движках. Итак, используйте то, что кажется вам эстетически лучше. Для меня это распространение.
...
это чистая красота.
Если вы решили использовать slice, пропустите 0, просто скажите .slice()
.