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
|
---
title: 剩余参数
slug: Web/JavaScript/Reference/Functions/Rest_parameters
tags:
- Functions
- JavaScript
- Rest
- Rest parameters
translation_of: Web/JavaScript/Reference/Functions/rest_parameters
---
<div>{{jsSidebar("Functions")}}</div>
<p><strong>剩余参数</strong>语法允许我们将一个不定数量的参数表示为一个数组。</p>
<div>{{EmbedInteractiveExample("pages/js/functions-restparameters.html")}}</div>
<h2 id="语法">语法</h2>
<pre class="brush: js">function(a, b, ...theArgs) {
// ...
}
</pre>
<h2 id="描述">描述</h2>
<p>如果函数的最后一个命名参数以<code>...</code>为前缀,则它将成为一个由剩余参数组成的真数组,其中从<code>0</code>(包括)到<code>theArgs.length</code>(排除)的元素由传递给函数的实际参数提供。</p>
<p>在上面的例子中,<code>theArgs</code>将收集该函数的第三个参数(因为第一个参数被映射到<code>a</code>,而第二个参数映射到<code>b</code>)和所有后续参数。</p>
<h3 id="剩余参数和_arguments对象的区别">剩余参数和 <code>arguments</code>对象的区别</h3>
<p>剩余参数和 <code><a href="/zh-cn/JavaScript/Reference/Functions_and_function_scope/arguments" title="arguments">arguments</a></code>对象之间的区别主要有三个:</p>
<ul>
<li>剩余参数只包含那些没有对应形参的实参,而 <code>arguments</code> 对象包含了传给函数的所有实参。</li>
<li><code>arguments</code>对象不是一个真正的数组,而剩余参数是真正的 <code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array" title="Array">Array</a></code>实例,也就是说你能够在它上面直接使用所有的数组方法,比如 <code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array/sort" title="Array sort method">sort</a></code>,<code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array/map" title="Array map method">map</a></code>,<code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array/forEach" title="Array forEach method">forEach</a></code>或<code><a href="/zh-cn/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="从_arguments_到数组">从 arguments 到数组</h3>
<p>引入了剩余参数来减少由参数引起的样板代码。</p>
<pre><code>// Before rest parameters, "arguments" could be converted to a normal array using:
function f(a, b) {
var normalArray = Array.prototype.slice.call(arguments);
// -- or --
var normalArray = [].slice.call(arguments);
// -- or --
var normalArray = Array.from(arguments);
var first = normalArray.shift(); // OK, gives the first argument
var first = arguments.shift(); // ERROR (arguments is not a normal array)
}
// Now we can easily gain access to a normal array using a rest parameter
function f(...args) {
var normalArray = args;
var first = normalArray.shift(); // OK, gives the first argument
}</code></pre>
<h3 id="解构剩余参数">解构剩余参数</h3>
<p>剩余参数可以被解构,这意味着他们的数据可以被解包到不同的变量中。请参阅<a href="/zh-CN/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 and c are undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (the fourth parameter is not destructured)</pre>
<h2 id="Example" name="Example">示例</h2>
<p>因为<code>theArgs</code>是个数组,所以你可以使用<code>length</code>属性得到剩余参数的个数:</p>
<pre class="brush: js">function fun1(...theArgs) {
alert(theArgs.length);
}
fun1(); // 弹出 "0", 因为theArgs没有元素
fun1(5); // 弹出 "1", 因为theArgs只有一个元素
fun1(5, 6, 7); // 弹出 "3", 因为theArgs有三个元素</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>arguments</code>对象不可以:</p>
<pre class="brush: js">function sortRestArgs(...theArgs) {
var sortedArgs = theArgs.sort();
return sortedArgs;
}
alert(sortRestArgs(5,3,7,1)); // 弹出 1,3,5,7
function sortArguments() {
var sortedArgs = arguments.sort();
return sortedArgs; // 不会执行到这里
}
alert(sortArguments(5,3,7,1)); // 抛出TypeError异常:arguments.sort is not a function
</pre>
<p>为了在<code>arguments</code>对象上使用<code>Array</code>方法,它必须首先被转换为一个真正的数组。</p>
<pre class="brush: js">function sortArguments() {
var args = Array.prototype.slice.call(arguments);
var sortedArgs = args.sort();
return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // shows 1, 3, 5, 7</pre>
<h2 id="Specifications" name="Specifications">规范</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>
<p>{{Compat("javascript.functions.rest_parameters")}}</p>
<h2 id="See_also" name="See_also">相关链接</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator" title="spread operator">Spread operator</a> (also ‘<code>...</code>’)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments" title="arguments">Arguments object</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" title="Array">Array</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions" title="Functions and function scope">Functions</a></li>
<li><a href="http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters">Original proposal at ecmascript.org</a></li>
<li><a href="http://javascriptweblog.wordpress.com/2011/01/18/javascripts-arguments-object-and-beyond/">JavaScript arguments object and beyond</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Destructuring assignment</a></li>
</ul>
|