---
title: Spread syntax
slug: Web/JavaScript/Reference/Operators/Spread_syntax
translation_of: Web/JavaScript/Reference/Operators/Spread_syntax
---
<div>{{jsSidebar("Operators")}}</div>

<div><strong>Spread syntax</strong> позволяет расширить доступные для итерации элементы (например, массивы или строки) в местах</div>

<ul>
 <li>для функций: где ожидаемое количество аргументов для вызовов функций равно нулю или больше нуля</li>
 <li>для элементов (литералов массива)</li>
 <li>для выражений объектов: в местах, где количество пар "ключ-значение" должно быть равно нулю или больше (для объектных литералов)</li>
</ul>

<div>{{EmbedInteractiveExample("pages/js/expressions-spreadsyntax.html")}}</div>

<p class="hidden">Источник для этого интерактивного примера находится в репозитории на GitHub. Если вы желаете внести свой вклад в этот проект, то, пожалуйста, склонируйте  себе <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> и пришлите нам pull request.</p>

<h2 id="Синтаксис">Синтаксис</h2>

<p>Для вызовов функций:</p>

<pre class="syntaxbox notranslate">myFunction(...iterableObj);
</pre>

<p>Для литералов массива или строк:</p>

<pre class="syntaxbox notranslate">[...iterableObj, '4', 'five', 6];</pre>

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

<pre class="syntaxbox notranslate">let objClone = { ...obj };</pre>

<h2 id="Примеры">Примеры</h2>

<h3 id="Spread_в_вызовах_функций">Spread в вызовах функций</h3>

<h4 id="Замена_apply">Замена apply</h4>

<p>Обычно используют {{jsxref( "Function.prototype.apply")}} в случаях, когда хотят использовать элементы массива в качестве аргументов функции.</p>

<pre class="brush: js notranslate">function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);</pre>

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

<pre class="brush: js notranslate">function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);</pre>

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

<pre class="brush: js notranslate">function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);</pre>

<h4 id="Apply_для_new">Apply для new</h4>

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

<pre class="brush: js notranslate">var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);
</pre>

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

<pre class="brush: js notranslate">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"}</pre>

<h3 id="Spread_в_литералах_массива">Spread в литералах массива</h3>

<h4 id="Более_мощный_литерал_массива">Более мощный литерал массива</h4>

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

<pre class="brush: js notranslate">var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
// ["head", "shoulders", "knees", "and", "toes"]
</pre>

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

<h4 id="Копирование_массива">Копирование массива</h4>

<pre class="brush: js notranslate">var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4);

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

<p><strong>Примечание:</strong> Spread syntax на самом деле переходит лишь на один уровень глубже при копировании массива. Таким образом, он может не подходить для копирования многоразмерных массивов, как показывает следующий пример: (также как и c {{jsxref("Object.assign()")}}) и синтаксис spred </p>

<pre class="brush: js notranslate">const a = [[1], [2], [3]];
const b = [...a];
b.shift().shift(); // 1
// О нет. Теперь на массив "а" относятся также: а
//[[], [2], [3]]
</pre>

<h4 id="Лучший_способ_конкатенации_массивов">Лучший способ конкатенации массивов</h4>

<p>Для конкатенации массива часто используется {{jsxref("Array.concat")}}:</p>

<pre class="brush: js notranslate">var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);</pre>

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

<pre class="brush: js notranslate">var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
</pre>

<p>{{jsxref("Array.unshift")}} часто используется для вставки массива значений в начало существующего массива. Без spread syntax:</p>

<pre class="brush: js notranslate">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]</pre>

<p>С использованием spread syntax [Следует отметить, что такой способ создает новый массив <code>arr1</code>. В отличие от {{jsxref("Array.unshift")}}, исходный массив не мутируется]:</p>

<pre class="brush: js notranslate">var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]
</pre>

<h3 id="Spread_в_литералах_объекта">Spread в литералах объекта</h3>

<p>Предложение <a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript</a> (стадия 4) добавляет свойства spread в <a href="/ru/docs/Web/JavaScript/Reference/Operators/Object_initializer">литералы объекта</a>. Оно копирует собственные перечисляемые свойства данного объекта в новый объект.</p>

<p>Поверхностное копирование (без прототипа) или объединение объектов теперь возможно с использованием более короткого, чем {{jsxref("Object.assign()")}}, синтаксиса.</p>

<pre class="brush: js notranslate">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 }</pre>

<p>Обратите внимание, что {{jsxref("Object.assign()")}} запускает <a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setters</a>, а <strong>spread syntax</strong> нет.</p>

<p>Обратите внимание, что вы не можете заменить или имитировать функцию {{jsxref("Object.assign()")}}:</p>

<pre class="brush: js notranslate">var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) =&gt; ( { ...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 } }</pre>

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

<h3 id="Только_для_итерируемых_объектов">Только для итерируемых объектов</h3>

<p>Spread syntax ( кроме случаев spread properties) может быть применен только к итерируемым объектам (<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator">iterable</a> objects) :</p>

<pre class="brush: js notranslate">var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable
</pre>

<h3 id="Spread_с_большим_количеством_значений">Spread с большим количеством значений</h3>

<p>При использовании spread оператора в вызовах функций необходимо быть внимательным к возможному переполнению в ядре JavaScript. Существует ограничение по максимально возможному количеству аргументов функции. См. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" title="The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object)."><code>apply()</code></a> для уточнения.</p>

<h2 id="Rest_синтаксис_параметры">Rest синтаксис (параметры)</h2>

<p>Синтаксис для rest оператора выглядит таким же как и для spread оператора, однако он используется для деструктуризации массивов и объектов. Фактически, rest оператор противоположен spread оператору: последний раскладывает массив на элементы, тогда как первый собирает много элементов в один. См. <a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters">rest parameters.</a></p>

<h2 id="Specifications">Specifications</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ES2015', '#sec-array-initializer')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Defined in several sections of the specification: <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer">Array Initializer</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-argument-lists">Argument Lists</a></td>
  </tr>
  <tr>
   <td>{{SpecName('ES2018', '#sec-object-initializer')}}</td>
   <td>{{Spec2('ES2018')}}</td>
   <td>Defined in <a href="http://www.ecma-international.org/ecma-262/9.0/#sec-object-initializer">Object Initializer</a></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-array-initializer')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>Без изменений.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-object-initializer')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>Без изменений.</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility">Browser compatibility</h2>



<p>{{Compat("javascript.operators.spread")}}</p>

<h2 id="See_also">See also</h2>

<ul>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters">Rest parameters</a> (also ‘<code>...</code>’)</li>
 <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">fn.apply</a> (also ‘<code>...</code>’)</li>
</ul>