1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
---
title: Sintaxe de Espalhamento
slug: Web/JavaScript/Reference/Operators/Spread_syntax
tags:
- ECMAScript 2015
- Iterator
- JavaScript
translation_of: Web/JavaScript/Reference/Operators/Spread_syntax
---
<div>{{jsSidebar("Operators")}}</div>
<div><strong>Sintaxe de Espalhamento (Spread syntax)</strong> permite que um objeto iterável, como uma expressão de array ou uma string seja expandido para ser usado onde zero ou mais argumentos (para chamadas de funções) ou elementos (para arrays <em>literais</em>) são esperados, ou que um objeto seja expandido onde zero ou mais pares <em>propriedade:valor</em> (para objetos <em>literais</em>) são esperados.</div>
<div></div>
<div>{{EmbedInteractiveExample("pages/js/expressions-spreadsyntax.html")}}</div>
<p class="hidden">O código-fonte para este exemplo interativo está armazenado em um repositorio do GitHub. Se você gostaria de contribuir para os exemplos interativos para este projeto, por favor clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> e nos envie um pull request.</p>
<h2 id="Sintaxe">Sintaxe</h2>
<p>Para chamada de funções:</p>
<pre class="syntaxbox">myFunction(...iterableObj);
</pre>
<p>Para arrays literais ou strings:</p>
<pre class="syntaxbox">[...iterableObj, '4', 'five', 6];</pre>
<p>Para objetos literais (novo em ECMAScript 2018; stage 3 draft):</p>
<pre class="syntaxbox">let objClone = { ...obj };</pre>
<h2 id="Exemplos">Exemplos</h2>
<h3 id="Espalhamento_e_chamadas_de_funções">Espalhamento e chamadas de funções</h3>
<h4 id="Substituindo_apply">Substituindo apply</h4>
<p>É comum usar {{jsxref( "Function.prototype.apply")}} em casos onde você quer usar os elementos de um array como argumentos para uma função.</p>
<pre class="brush: js">function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);</pre>
<p>Com a sintaxe de espalhamento, o código acima pode ser escrito assim:</p>
<pre class="brush: js">function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);</pre>
<p>Qualquer argumento numa lista de argumentos pode usar a sintaxe de espalhamento e pode ser usado mais de uma vez.</p>
<pre class="brush: js">function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);</pre>
<h4 id="Apply_para_new">Apply para new</h4>
<p>Quando um construtor é chamado com <code>new</code>, não é possivel usar diretamente um array e <code>apply</code> (<code>apply</code> executa o <code>[[Call]]</code> e não o <code>[[Construct]]</code>). No entanto, um array pode facilmente ser usado com <code>new</code> graças ao operador de espalhamento:</p>
<pre class="brush: js">var dateFields = [1970, 0, 1]; // 1 Jan 1970
var d = new Date(...dateFields);
</pre>
<p>Para usar o <code>new</code> com array de parâmetros sem a sintaxa de espalhamento, você teria que fazer isso <strong>indiretamente </strong>por meio da aplicação parcial:</p>
<pre class="brush: js">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="Espalhamento_em_arrays_literais">Espalhamento em arrays literais</h3>
<h4 id="Um_array_literal_mais_poderoso">Um array literal mais poderoso</h4>
<p>Criar um novo array usando um array existente como parte dele, não é possível utilizando apenas a sintaxe de array literal. O código imperativo deve ser usado ao invés da combinação de <code>push</code>, <code>splice</code>, <code>concat</code>, etc. Com a sintaxe de espalhamento isso se torna muito mais sucinto:</p>
<pre class="brush: js">var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
// ["head", "shoulders", "knees", "and", "toes"]
</pre>
<p>Assim como espalhar a lista de argumentos, <code>...</code> pode ser usado em qualquer lugar em um array literal e pode ser usado multiplas vezes.</p>
<h4 id="Copiando_um_array">Copiando um array</h4>
<pre class="brush: js">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>Nota:</strong> A sintaxe de espalhamento efetivamente vai um nível mais profundo quando se copia um array. Assim sendo, pode ser inadequado para copiar arrays multidimensionais como o exemplo a seguir mostra (é o mesmo com {{jsxref("Object.assign()")}} e a sintaxe de espalhamento).</p>
<pre class="brush: js">var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array a is affected as well: [[], [2], [3]]
</pre>
<h4 id="Uma_maneira_melhor_de_concatenar_arrays">Uma maneira melhor de concatenar arrays</h4>
<p>{{jsxref("Array.concat")}} é frequentemente usado para concatenar um array no final de um array existente. Sem a sintaxe de espalhamento é feito assim:</p>
<pre class="brush: js">var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);</pre>
<p>Com a sintaxe de espalhamento se torna isso:</p>
<pre class="brush: js">var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
</pre>
<p>{{jsxref("Array.unshift")}} é frequentemente usado para inserir um array de valores no inicio de um array existente. Sem a sintaxe de espalhamento é feito assim:</p>
<pre class="brush: js">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>Com a <em>sintaxe de espalhamento</em> isso se torna <em>[Note, no entanto, que isso cria um novo <code>arr1</code> array. Ao contrário de {{jsxref("Array.unshift")}}, isso não modifica o array original <code>arr1</code> array]</em>:</p>
<pre class="brush: js">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="Espalhamento_em_objetos_literais">Espalhamento em objetos literais</h3>
<p>A proposta <a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript</a> (stage 3) adiciona espalhamento de propriedades para <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">objetos literais</a>. Este copia as propriedades enumeráveis de um objeto informado em um novo objeto.</p>
<p><strong>Cópia-rasa (Shallow-cloning)</strong> (excluindo o protótipo) ou fusão (<strong>merge</strong>) de objetos agora é possivel usando uma sintaxe mais curta que {{jsxref("Object.assign()")}}.</p>
<pre class="brush: js">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>Note que {{jsxref("Object.assign()")}} chamada os <a href="/en-US/docs/Web/JavaScript/Reference/Functions/set">setters</a> e a <em>sintaxe de espalhamento</em> não.</p>
<h3 id="Apenas_para_iteráveis">Apenas para iteráveis</h3>
<p>A sintaxe de espalhamento (diferente de propriedades espalhadas) só pode ser utilizada com objetos iteráveis.</p>
<pre class="brush: js">var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable
</pre>
<h3 id="Espalhamento_com_muitos_valores">Espalhamento com muitos valores</h3>
<p>Quando usar a sintaxe de espalhamento para chamada de funções, esteja ciente da possibilidade de exceder tamanho máximo de argumentos do motor do Javascript. Veja <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> para mais detalhes.</p>
<h2 id="Sintaxe_Rest_parâmetros">Sintaxe Rest (parâmetros)</h2>
<p>A <em>sintaxe rest</em> se parece exatamente como a <em>sintaxe de espalhamento</em>, mas esta é usada para desestruturar arrays e objetos. De certa forma, a <em>sintaxe rest</em> é o oposto da <em>sintaxe de espalhamento</em>: A <em>sintaxe de espalhamento (spread)</em> 'expande' um array em vários elementos, enquanto a <em>sintaxe rest</em> coleta multiplos elementos e 'condensa' eles em um único elemento. Veja <a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters">parâmetros rest.</a></p>
<h2 id="Especificações">Especificações</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('ESDraft', '#sec-array-initializer')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td>No changes.</td>
</tr>
<tr>
<td><a href="https://github.com/tc39/proposal-object-rest-spread">Rest/Spread Properties for ECMAScript </a></td>
<td>Draft</td>
<td>Stage 3 draft.</td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidade_com_Navegadores">Compatibilidade com Navegadores</h2>
<div class="hidden">A tabela de compatibilidade nessa página é gerada a partir de dados estruturados. Se você gostaria de contribuir com dados, por favor verifique <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> e nos mande um pull request.</div>
<p>{{Compat("javascript.operators.spread")}}</p>
<h2 id="Veja_também">Veja também</h2>
<ul>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters">Parâmetros Rest</a> (also ‘<code>...</code>’)</li>
</ul>
|