Spread-оператор позволяет разложить объект на список пар "ключ:значение". Как ни странно, такой список может понадобиться при создании нового объекта. Ведь синтаксис создания объекта подразумевает список — в фигурных скобках надо перечислить пары "ключ:значение" будущего объекта { список }:

const user = { name: 'Vasya', married: true, age: 25 };

И вот как выглядит применение spread-оператора:

const user = { name: 'Vasya', married: true, age: 25 };

const newUser = { ...user };
console.log(newUser); // => { name: 'Vasya', married: true, age: 25 }

Давайте разберём, что произошло и какие преимущества у такого подхода:

  • Копирование объекта, а не ссылки на объект.

В операции const newUser = { ...user }; создаётся новый объект — копия объекта user — и в константу newUser сохраняется новая ссылка на новый объект. Теперь user и newUser указывают на разные объекты. То есть это хороший способ сделать копию объекта.

  • Конструирование нового объекта на основе старого.

    const user = { name: 'Vasya' };
    
    const newUser = { ...user, married: true, age: 25 };
    console.log(newUser); // => { name: 'Vasya', married: true, age: 25 }
    

    Как видно, можно использовать исходный объект только как одну из частей для нового объекта.

  • Слияние нескольких объектов.

    const user = { name: 'Vasya' };
    const characteristics = { married: true, age: 25 };
    
    const mergedObject = { ...user, ...characteristics };
    console.log(mergedObject); // => { name: 'Vasya', married: true, age: 25 }
    

    Если у объектов есть одинаковые ключи, то при слиянии в итоговый объект будет записано значение ключа того объекта, который был расположен правее:

    const user = { name: 'Vasya', married: true, age: 25 };
    const user2 = { name: 'Petya', surname: 'Ivanov' };
    
    const mergedObject = { ...user, ...user2 };
    console.log(mergedObject); // => { name: 'Petya', married: true, age: 25, surname: 'Ivanov' }
    
    // поменяли местами объекты
    const mergedObject2 = { ...user2, ...user };
    console.log(mergedObject2); // => { name: 'Vasya', surname: 'Ivanov', married: true, age: 25 }
    

    У обоих объектов есть общее свойство name, поэтому при их слиянии значение будет браться от объекта, стоящего правее в операции слияния. Поэтому в первом случае { ...user, ...user2 } значение ключа name из user2 перезаписало значение из user. А во втором { ...user2, ...user } — наоборот, записано значение из user.

    Таким образом, порядок объектов при их слиянии может влиять на итоговый результат. Обратите внимание на этот случай, очень часто возникают ошибки (неожиданные результаты) из-за неправильного порядка.

  • Гибкое конструирование. Может быть задействовано любое количество spread-операторов и в любом порядке:

    const user = { name: 'Vasya', age: 25 };
    const user2 = { name: 'Petya', surname: 'Ivanov' };
    
    const newUser = { ...user, married: true, ...user2 };
    console.log(newUser); // => { name: 'Petya', age: 25, married: true, surname: 'Ivanov' }
    
    const married = true;
    const property = 'middleName'; // для задания динамического свойства
    const newUser2 = {
      married,
      [property]: 'Nikolaevich',
      ...{ ...user, ...user2 },
    };
    console.log(newUser2); // =>
    // { married: true,
    //   middleName: 'Nikolaevich',
    //   name: 'Petya',
    //   age: 25,
    //   surname: 'Ivanov' }
    

Этот приём часто используется на практике при создании объектов. Возьмите его себе на вооружение. //: # (FIXME:repl: добавить про Object.assign?)

Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →