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
|
---
title: 其餘參數
slug: Web/JavaScript/Reference/Functions/rest_parameters
translation_of: Web/JavaScript/Reference/Functions/rest_parameters
---
<div>{{jsSidebar("Functions")}}</div>
<p><strong>其餘參數(rest parameter)</strong> 語法可以讓我們表示不確定數量的參數,並將其視為一個陣列。</p>
<h2 id="語法">語法</h2>
<pre class="brush: js">function f(a, b, ...theArgs) {
// ...
}
</pre>
<h2 id="描述">描述</h2>
<p>如果函式的最後一個命名參數以 <code>...</code> 開頭,它會被視為一個陣列。該陣列的元素會被置於索引從 <code>0</code>(含)到的 <code>theArgs.length</code>(不含)位置,並且被視為一個函式的參數。</p>
<p>在上面的範例中,<code>theArgs</code> 會將函式f中第三個(含)以後的參數收集起來。</p>
<h3 id="其餘參數和_arguments_物件的差異">其餘參數和 <code>arguments</code> 物件的差異</h3>
<p>以下是其餘參數和 <code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments" title="arguments">arguments</a> 物件</code>三個主要的差異:</p>
<ul>
<li>其餘參數是 <code>arguments</code> 物件被傳入到函式的時候,還沒被指定變數名稱的引數。</li>
<li><code>arguments</code> 物件不是一個實際的陣列,而 rest parameter 是陣列的實體,即 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort" title="Array sort method">sort</a></code>、<code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" title="Array map method">map</a></code><font face="Open Sans, arial, x-locale-body, sans-serif">、</font><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" title="Array forEach method">forEach</a></code> <font face="Open Sans, arial, x-locale-body, sans-serif">或 </font><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop" title="Array pop method">pop</a></code> 可以直接在其餘參數被調用。</li>
<li><code>arguments</code> 物件自身有額外的功能,例如 <code>callee</code> 屬性。</li>
</ul>
<h3 id="將參數轉成陣列">將參數轉成陣列</h3>
<p>其餘參數被介紹作為取代用 arguments 寫的範例程式。</p>
<pre class="brush: js">// 在有其餘參數之前,你可能見過下面的程式碼:
function f(a, b) {
var args = Array.prototype.slice.call(arguments, f.length); // f.length 表示 arguments 的數量
// …
}
// 現在可以寫成這樣
function f(a, b, ...args) {
}
</pre>
<h3 id="解構其餘參數_rest_parameters">解構其餘參數 rest parameters</h3>
<p>其餘參數可以被解構,換句話說,可以把這個陣列解開,並將各個元素取出成為個別的變數。請參考<a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">解構賦值</a>。</p>
<pre class="brush: js">function f(...[a, b, c]) {
return a + b + c;
}
f(1) // NaN (b 和 c 都是 undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (第四個參數不會被解構,因為解構式只有三個定義好的變數名稱)</pre>
<h2 id="範例">範例</h2>
<p>因為 <code>theArgs</code> 是一個陣列,所以它會有 <code>length</code> 屬性,作為表示參數數量:</p>
<pre class="brush: js">function fun1(...theArgs) {
console.log(theArgs.length);
}
fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3
</pre>
<p>在接下來的範例中,其餘參數被用來收集第一個之後的所有引數並存在陣列中。 在這個陣列裡的每個元素(數字),都會和第一個參數相乘後取代原本的元素,最後再將取代元素後的陣列回傳。</p>
<pre class="brush: js">function multiply(multiplier, ...theArgs) {
return theArgs.map(function(element) {
return multiplier * element;
});
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
</pre>
<p>下列範例展示 <code>Array</code> 的方法可以在其餘參數上被使用,但 <code>arguments</code> 則不行。</p>
<pre class="brush: js">function sortRestArgs(...theArgs) {
var sortedArgs = theArgs.sort();
return sortedArgs;
}
console.log(sortRestArgs(5, 3, 7, 1)); // 顯示 1, 3, 5, 7
function sortArguments() {
var sortedArgs = arguments.sort();
return sortedArgs; // 因為前一行會因為 arguments 沒有sort()這個方法而造成TypeError,所以永遠不會執行此行。
}
console.log(sortArguments(5, 3, 7, 1)); // 會拋出 TypeError (arguments.sort is not a function)
</pre>
<p>為了要在 <code>arguments</code> 物件上使用 <code>Array</code> 的方法,可以將它轉換成真的 <code>Array</code> 實體,或者以 <code>apply()</code> 直接調用需要的方法。</p>
<pre class="brush: js">function sortArguments() {
var args = Array.from(arguments);
var sortedArgs = args.sort();
return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // 顯示 1, 3, 5, 7
</pre>
<h2 id="規範">規範</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-function-definitions', 'Function Definitions')}}</td>
<td>{{Spec2('ES6')}}</td>
<td>Initial definition</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-function-definitions', 'Function Definitions')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="瀏覽器相容性">瀏覽器相容性</h2>
<div>
<p>{{Compat("javascript.functions.rest_parameters")}}</p>
</div>
<h2 id="參見">參見</h2>
<ul>
<li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator" title="spread operator">Spread operator</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>
|