Понимание оператора распространения в JavaScript
Новые версии JavaScript внесли значительные улучшения в язык с точки зрения выразительности и простоты разработки, но быстрый темп изменений заставляет многих разработчиков чувствовать, что они изо всех сил стараются не отставать.
Теперь, когда WordPress использует React и современный JavaScript в новом редакторе Gutenberg, огромная аудитория разработчиков WordPress попадает в этот мир, нравится нам это или нет, и быстро пытается наверстать упущенное.
В этом посте мы рассмотрим одну из самых популярных новых функций языка JavaScript — оператор Spread (также известный как ...
оператор).
Друг недавно попросил помощи в понимании некоторых примеров кода из библиотеки блоков Гутенберга, в частности галереи. На момент написания этой статьи этот код можно увидеть здесьно он несколько раз перемещался, поэтому я воспроизвел его ниже:
setImageAttributes( index, attributes ) {
const { attributes: { images }, setAttributes } = this.props;
if ( ! images[index] ) {
return;
}
setAttributes( {
images: [
...images.slice( 0, index ),
{
...images[ index],
...attributes,
},
...images.slice( index + 1 ),
],
} );
}
В частности, сбивающей с толку частью было:
images: [
...images.slice( 0, index ),
{
...images[ index],
...attributes,
},
...images.slice( index + 1 ),
],
Это, безусловно, выглядит немного пугающе, особенно если в последнее время вы не тратите все свое время на кодирование современного JavaScript. Разбираем происходящее.
Операторы расширения для массивов
Основная часть, которую нужно знать, это ...
синтаксис. Это оператор расширения, и он, по сути, берет либо массив, либо объект и расширяет его до набора элементов. Это позволяет вам делать необычные вещи, например, если у вас есть код:
const array = [1, 2];
const array2 = [...array, 3, 4];
Значение array2 в конечном итоге будет [1, 2, 3, 4]
.
Оператор распространения позволяет вам по существу вставить массив и получить его значения.
Возвращаясь к нашему исходному примеру кода, на внешнем уровне у нас есть
images = [...images.slice(0, index), {some stuff}, ...images.slice(index+1)]
Это говорит о следующем: установите массив изображений как массив старых изображений от 0 до индекса, за которым следует новая вещь, которую мы вскоре рассмотрим, а затем массив старых изображений от индекса + 1 до конца.
Другими словами, мы собираемся заменить элемент в index
.
Операторы распространения для объектов
Далее, для объектов, синтаксис распространения которых позволяет вам сделать эквивалент Object.assign, копируя значения объекта в новый. Глядя на простой пример кода:
const obj1 = {a: 'a', b: 'b'};
const obj2 = {c: 'c', ...obj1};
Это приводит к obj2
существование {a: 'a', b: 'b', c: 'c'}
.
Возвращаясь к примеру кода Гутенберга, внутренний уровень (помеченный как {some stuff}
в нашей оценке массива) мы имеем:
{
...images[index],
...attributes,
}
Чтобы перевести: создайте объект, сначала заполните его значениями из images[index]
а затем со значениями из attributes
. Любые повторяющиеся значения перезаписываются более поздним.
Итак, это говорит: возьмите мой старый образ из index
и примените любые значения, которые у меня есть в attributes
к нему со значениями в attributes
имеет приоритет.
Если мы вернемся ко всему нашему примеру кода:
images: [
...images.slice( 0, index ),
{
...images[ index],
...attributes,
},
...images.slice( index + 1 ),
],
Вся эта большая причудливая штука говорит: у меня есть массив изображений, индекс и набор атрибутов, которые я хочу применить. Возвращает новый массив изображений, который изменяет элемент в index
иметь мои новые атрибуты.
Расширенный синтаксис позволяет создавать компактный и выразительный код
Давайте посмотрим, что у нас получилось. В одном коротком, надеюсь, теперь читабельном выражении нам удалось создать новую копию массива, который имеет обновленный сложный объект по определенному индексу. Мы не изменили исходный массив, а это означает, что другие части нашего кода могут вызывать его, не опасаясь побочных эффектов. Красивый.