В процессе перевода.

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

Синтаксис

Для вызовов функций:

myFunction(...iterableObj);

Для литералов массива или строк:

[...iterableObj, '4', 'five', 6];

Для литералов объекта (новое в ECMAScript 2018):

let objClone = { ...obj };

Примеры

Spread в вызовах функций

Замена apply

Обычно используют Function.prototype.apply в случаях, когда хотят использовать элементы массива в качестве аргументов функции.

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);

С spread syntax вышеприведенное можно записать как:

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

Любой аргумент в списке аргументов может использовать spread syntax, и его можно использовать несколько раз.

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

Apply для new

Вызывая конструктор через ключевое слово new, невозможно использовать массив и apply напрямую (apply выполняет [[Call]], а не [[Construct]]).Однако благодаря spread syntax, массив может быть с легкостью использован со словом new:

var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

Чтобы использовать new с массивом параметров без spread syntax, вам потребуется использование частичного применения:

function applyAndNew(constructor, args) {
   function partial () {
      return constructor.apply(this, args);
   };
   if (typeof constructor.prototype === "object") {
      partial.prototype = Object.create(constructor.prototype);
   }
   return partial;
}


function myConstructor () {
   console.log("arguments.length: " + arguments.length);
   console.log(arguments);
   this.prop1="val1";
   this.prop2="val2";
};

var myArguments = ["hi", "how", "are", "you", "mr", null];
var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);

console.log(new myConstructorWithArguments);
// (internal log of myConstructor):           arguments.length: 6
// (internal log of myConstructor):           ["hi", "how", "are", "you", "mr", null]
// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

Spread в литералах массива

Более мощный литерал массива

Без spread syntax, применение синтаксиса литерала массива для создания нового массива на основе существующего недостаточно и требуется императивный код вместо комбинации методов push, splice, concat и т.д. С spread syntax реализация становится гораздо более лаконичной:

var parts = ['shoulders', 'knees']; 
var lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

Аналогично развертыванию в массиве аргументов, ... может быть использован повсеместно и многократно в литерале массива.

Копирование массива

var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4); 

// arr2 becomes [1, 2, 3, 4]
// arr remains unaffected

Примечание: Spread syntax на самом деле переходит лишь на один уровень глубже при копировании массива. Таким образом, он может не подходить для копирования многоразмерных массивов, как показывает следующий пример: (также как и Object.assign())

var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array a is affected as well: [[], [2], [3]]

Лучший способ конкатенации массивов

Для конкатенации массива часто используется Array.concat:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);

С использованием spread syntax:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift часто используется для вставки массива значений в начало существующего массива. Без spread syntax:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Prepend all items from arr2 onto arr1
Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]

С использованием spread syntax [Следует отметить, что такой способ создает новый массив arr1. В отличие от Array.unshift, исходный массив не мутируется]:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]

Spread в литералах объекта

Предложение Rest/Spread Properties for ECMAScript (стадия 4) добавляет свойства spread в литералы объекта. Оно копирует собственные перечисляемые свойства данного объекта в новый объект.

Поверхностное копирование (без прототипа) или объединение объектов теперь возможно с использованием более короткого, чем Object.assign(), синтаксиса.

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

Обратите внимание, что Object.assign() запускает setters, а spread syntax нет.

Обратите внимание, что вы не можете заменить или имитировать функцию Object.assign():

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );

var mergedObj = merge ( obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }

var mergedObj = merge ( {}, obj1, obj2);
// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }

В приведенном выше примере оператор распространения не работает так, как можно было бы ожидать: он распространяет массив аргументов в литерал объекта благодаря параметру rest.

Только для итерируемых объектов

Spread syntax ( кроме случаев spread properties) может быть применен только к итерируемым объектам (iterable objects) :

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

Spread with many values

When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit. See apply() for more details.

Rest syntax (parameters)

Rest syntax looks exactly like spread syntax, but is used for destructuring arrays and objects. In a way, rest syntax is the opposite of spread syntax: spread 'expands' an array into its elements, while rest collects multiple elements and 'condenses' them into a single element. See rest parameters.

Specifications

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262) Стандарт Defined in several sections of the specification: Array Initializer, Argument Lists
ECMAScript 2018 (ECMA-262) Стандарт Defined in Object Initializer
ECMAScript Latest Draft (ECMA-262) Черновик No changes.
ECMAScript Latest Draft (ECMA-262) Черновик No changes.

Browser compatibility

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidEdge MobileFirefox для AndroidOpera для AndroidSafari on iOSSamsung InternetNode.js
Spread in array literalsChrome Полная поддержка 46Edge Полная поддержка 12Firefox Полная поддержка 16IE Нет поддержки НетOpera Полная поддержка 37Safari Полная поддержка 8WebView Android Полная поддержка 46Chrome Android Полная поддержка 46Edge Mobile Полная поддержка 12Firefox Android Полная поддержка 16Opera Android Полная поддержка 37Safari iOS Полная поддержка 8Samsung Internet Android Полная поддержка 5.0nodejs Полная поддержка 5.0.0
Полная поддержка 5.0.0
Полная поддержка 4.0.0
Отключено
Отключено From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in function callsChrome Полная поддержка 46Edge Полная поддержка 12Firefox Полная поддержка 27IE Нет поддержки НетOpera Полная поддержка 37Safari Полная поддержка 8WebView Android Полная поддержка 46Chrome Android Полная поддержка 46Edge Mobile Полная поддержка 12Firefox Android Полная поддержка 27Opera Android Полная поддержка 37Safari iOS Полная поддержка 8Samsung Internet Android Полная поддержка 5.0nodejs Полная поддержка 5.0.0
Полная поддержка 5.0.0
Полная поддержка 4.0.0
Отключено
Отключено From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in destructuringChrome Полная поддержка 49Edge Нет поддержки НетFirefox Полная поддержка 34IE Нет поддержки НетOpera Полная поддержка 37Safari ? WebView Android Полная поддержка 49Chrome Android Полная поддержка 49Edge Mobile Нет поддержки НетFirefox Android Полная поддержка 34Opera Android Полная поддержка 37Safari iOS ? Samsung Internet Android Полная поддержка 5.0nodejs Полная поддержка Да
Spread in object literals
Экспериментальная
Chrome Полная поддержка 60Edge Нет поддержки НетFirefox Полная поддержка 55IE Нет поддержки НетOpera Полная поддержка 47Safari Полная поддержка 11.1WebView Android Полная поддержка 60Chrome Android Полная поддержка 60Edge Mobile Нет поддержки НетFirefox Android Полная поддержка 55Opera Android ? Safari iOS Полная поддержка 11.1Samsung Internet Android Полная поддержка 8.2nodejs Полная поддержка 8.3.0
Полная поддержка 8.3.0
Полная поддержка 8.0.0
Отключено
Отключено From version 8.0.0: this feature is behind the --harmony runtime flag.

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Совместимость неизвестна  
Совместимость неизвестна
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Экспериментальная. Ожидаемое поведение может измениться в будущем.
Пользователь должен сам включить эту возможность.
Пользователь должен сам включить эту возможность.

See also

Метки документа и участники

Внесли вклад в эту страницу: Ostanioni, Acrom7, mdnwebdocs-bot, R-Oscar, DenisIgnatchenko, dev1am, ue4prog
Обновлялась последний раз: Ostanioni,