This page was translated from English by the community.Learn more and join the MDN Web Docs community.
Spread syntax
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since октябрь 2015 г..
Spread syntax позволяет расширить доступные для итерации элементы (например, массивы или строки) в местах
- для функций: где ожидаемое количество аргументов для вызовов функций равно нулю или больше нуля
- для элементов (литералов массива)
- для выражений объектов: в местах, где количество пар "ключ-значение" должно быть равно нулю или больше (для объектных литералов)
In this article
Интерактивный пример
function sum(x, y, z) { return x + y + z;}const numbers = [1, 2, 3];console.log(sum(...numbers));// Expected output: 6console.log(sum.apply(null, numbers));// Expected output: 6Синтаксис
Для вызовов функций:
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 1970var 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 на самом деле переходит лишь на один уровень глубже при копировании массива. Таким образом, он может не подходить для копирования многоразмерных массивов, как показывает следующий пример: (также как и cObject.assign()) и синтаксис spred
const a = [[1], [2], [3]];const b = [...a];b.shift().shift(); // 1// О нет. Теперь на массив "а" относятся также: а//[[], [2], [3]]Лучший способ конкатенации массивов
Для конкатенации массива часто используетсяArray.concat:
var arr1 = [0, 1, 2];var arr2 = [3, 4, 5];// Append all items from arr2 onto arr1arr1 = 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 arr1Array.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 iterableSpread с большим количеством значений
При использовании spread оператора в вызовах функций необходимо быть внимательным к возможному переполнению в ядре JavaScript. Существует ограничение по максимально возможному количеству аргументов функции. См.apply() для уточнения.
Rest синтаксис (параметры)
Синтаксис для rest оператора выглядит таким же как и для spread оператора, однако он используется для деструктуризации массивов и объектов. Фактически, rest оператор противоположен spread оператору: последний раскладывает массив на элементы, тогда как первый собирает много элементов в один. См.rest parameters.
Спецификации
Совместимость с браузерами
Смотрите также
- Rest parameters (also '
...') - fn.apply (also '
...')