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
229
230
231
232
233
234
|
---
title: Parâmetros Rest
slug: Web/JavaScript/Reference/Funcoes/parametros_rest
tags:
- Funcionalidade Linguagem
- Funções
- JavaScript
- Parametros Rest
- Rest
translation_of: Web/JavaScript/Reference/Functions/rest_parameters
---
<div>Parâmetrois {{jsSidebar("Functions")}}</div>
<p><span class="seoSummary">A sintaxe do <strong>parâmetro "rest"</strong> permite-nos representar um número indefinido de argumentos</span><span class="seoSummary">como um <em>array</em>.</span></p>
<div>{{EmbedInteractiveExample("pages/js/functions-restparameters.html")}}</div>
<h2 id="Sintaxe">Sintaxe</h2>
<pre class="syntaxbox">function f(<var>a</var>, <var>b</var>, ...<var>theArgs</var>) {
// ...
}</pre>
<h2 id="Descrição">Descrição</h2>
<p>A function's last parameter can be prefixed with <code>...</code> which will cause all remaining (user supplied) arguments to be placed within a "standard" Javascript array.</p>
<p>Only the last parameter can be a "rest parameter".</p>
<pre class="brush: js">function myFun(<var>a</var>, <var>b</var>, ...<var>manyMoreArgs</var>) {
console.log("a", a)
console.log("b", b)
console.log("manyMoreArgs", manyMoreArgs)
}
myFun("one", "two", "three", "four", "five", "six")
// Console Output:
// a, one
// b, two
// manyMoreArgs, [three, four, five, six]
</pre>
<h3 id="Difference_between_rest_parameters_and_the_arguments_object">Difference between rest parameters and the <code>arguments</code> object</h3>
<p>There are three main differences between rest parameters and the {{jsxref("Functions/arguments", "arguments")}} object:</p>
<ul>
<li>rest parameters are only the ones that haven't been given a separate name (i.e. formally defined in function expression), while the <code>arguments</code> object contains <em>all</em> arguments passed to the function;</li>
<li>the <code>arguments</code> object is not a real array, while rest parameters are {{jsxref("Global_Objects/Array", "Array")}} instances, meaning methods like {{jsxref("Array.sort", "sort")}}, {{jsxref("Array.map", "map")}}, {{jsxref("Array.forEach", "forEach")}} or {{jsxref("Array/pop", "pop")}} can be applied on it directly;</li>
<li>the <code>arguments</code> object has additional functionality specific to itself (like the <code>callee</code> property).</li>
</ul>
<h3 id="From_arguments_to_an_array">From arguments to an array</h3>
<p>Rest parameters have been introduced to reduce the boilerplate code that was induced by the arguments</p>
<pre class="brush: js">// Before rest parameters, "arguments" could be converted to a normal array using:
function f(a, b) {
let normalArray = Array.prototype.slice.call(arguments)
// -- or --
let normalArray = [].slice.call(arguments)
// -- or --
let normalArray = Array.from(arguments)
let first = normalArray.shift() // OK, gives the first argument
let first = arguments.shift() // ERROR (arguments is not a normal array)
}
// Now, you can easily gain access to a normal array using a rest parameter
function f(...args) {
let normalArray = args
let first = normalArray.shift() // OK, gives the first argument
}
</pre>
<h3 id="Destructuring_rest_parameters">Destructuring rest parameters</h3>
<p>Rest parameters can be destructured Arrays only (though objects will soon be supported). That means that their data can be unpacked into distinct variables. (See <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Destructuring assignment</a>.)</p>
<pre class="brush: js">function f(...[a, b, c]) {
return a + b + c;
}
f(1) // NaN (b and c are undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (the fourth parameter is not destructured)
</pre>
<div class="blockIndicator note">
<h4 id="Fixme">Fixme</h4>
<p><s>Doing this is possible, but (afaik) there's no use-case, so it's just confusing the junior audience. The following code does exactly the same. There should at least be a note, that in theory you can do something like this, but there is no point in doing so.</s> The example is contrived, but imagine that [a, b, c] were the return value of some function. Then the utility is clear.</p>
<p><s>Also, since <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">Function arguments</a> will never have named parameters (this is not Python), the statement "objects will soon be supported" is wrong. </s> The preceding example may be mixing up destructuring with rest parameters. Please see the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">page on destructuring assignment</a> for an example with object destructuring applied in the parameters area.</p>
<pre class="brush: js">function f(a, b, c) {
return a + b + c
}
f(1) // NaN (b and c are undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (the fourth parameter is not ...)
</pre>
</div>
<h2 id="Exemplos">Exemplos</h2>
<p>In this example, the first argument is mapped to <code>a</code> and the second to <code>b</code>, so these named arguments are used like normal.</p>
<p>However, the third argument, <code>manyMoreArgs</code>, will be an array that contains the 3<sup>rd</sup>, 4<sup>th</sup>, 5<sup>th</sup>, 6<sup>th</sup> ... <var>n</var><sup>th</sup> — as many arguments that the user includes.</p>
<pre class="brush: js">function myFun(a, b, ...manyMoreArgs) {
console.log("a", a)
console.log("b", b)
console.log("manyMoreArgs", manyMoreArgs)
}
myFun("one", "two", "three", "four", "five", "six")
// a, one
// b, two
// manyMoreArgs, [three, four, five, six]
</pre>
<p>Below... even though there is just one value, the last argument still gets put into an array.</p>
<pre class="brush: js">// using the same function definition from example above
myFun("one", "two", "three")
// a, one
// b, two
// manyMoreArgs, [three]</pre>
<p>Below, the third argument isn't provided, but <code>manyMoreArgs</code> is still an array (albeit an empty one).</p>
<pre class="brush: js">// using the same function definition from example above
myFun("one", "two")
// a, one
// b, two
// manyMoreArgs, []</pre>
<p>Since <code>theArgs</code> is an array, a count of its elements is given by the <code>length</code> property:</p>
<pre class="brush: js">function fun1(...theArgs) {
console.log(theArgs.length)
}
fun1() // 0
fun1(5) // 1
fun1(5, 6, 7) // 3
</pre>
<p>In the next example, a rest parameter is used to collect all parameters after the first into an array. Each one of them is then multiplied by the first parameter, and the array is returned:</p>
<pre class="brush: js">function multiply(multiplier, ...theArgs) {
return theArgs.map(function(element) {
return multiplier * element
})
}
let arr = multiply(2, 1, 2, 3)
console.log(arr) // [2, 4, 6]
</pre>
<p><code>Array</code> methods can be used on rest parameters, but not on the <code>arguments</code> object:</p>
<pre class="brush: js">function sortRestArgs(...theArgs) {
let sortedArgs = theArgs.sort()
return sortedArgs
}
console.log(sortRestArgs(5, 3, 7, 1)) // 1, 3, 5, 7
function sortArguments() {
let sortedArgs = arguments.sort()
return sortedArgs // this will never happen
}
console.log(sortArguments(5, 3, 7, 1))
// throws a TypeError (arguments.sort is not a function)
</pre>
<p>To use <code>Array</code> methods on the <code>arguments</code> object, it must be converted to a real array first.</p>
<pre class="brush: js">function sortArguments() {
let args = Array.from(arguments)
let sortedArgs = args.sort()
return sortedArgs
}
console.log(sortArguments(5, 3, 7, 1)) // 1, 3, 5, 7
</pre>
<h2 id="Especificações">Especificações</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Especificação</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-function-definitions', 'Function Definitions')}}</td>
</tr>
</tbody>
</table>
<h2 id="Compatibildiade_de_navegador">Compatibildiade de navegador</h2>
<p>{{Compat("javascript.functions.rest_parameters")}}</p>
<h2 id="Consulte_também">Consulte também</h2>
<ul>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator" title="spread operator">Spread syntax</a> (also ‘<code>...</code>’)</li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments" title="arguments">Arguments object</a></li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" title="Array">Array</a></li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Functions" title="Functions and function scope">Functions</a></li>
<li><a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters">Original proposal at ecmascript.org</a></li>
<li><a class="external" href="http://javascriptweblog.wordpress.com/2011/01/18/javascripts-arguments-object-and-beyond/">JavaScript arguments object and beyond</a></li>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Destructuring assignment</a></li>
</ul>
|