Синтаксис спреда и метод среза

Я пытался понять, в чем разница между синтаксисом распространения и методом среза в следующем подходе.

Предположим, что я хочу сделать фактическую копию массива, я могу легко сделать это, используя распространенный синтаксис

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)

Ответ 3

Измерения в Chrome показывают, что срез гораздо более производительный, чем оператор распространения: 67 миллионов операций в секунду против 4 миллионов операций в секунду. Если вы создаете приложение для Chrome или приложения Electron (в котором используется Chromium), я бы предпочел слайс, особенно для приложений с большими данными и в реальном времени.

Measure results

EDIT:

Кажется, что оператор Spread теперь намного быстрее, хотя все еще медленнее, чем Slice:

Newer Measurement Results

Ответ 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().