2019-04-21 11:50:48 +08:00

227 lines
18 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article id="wikiArticle">
<div></div>
<p><strong>剩余参数</strong>语法允许我们将一个不定数量的参数表示为一个数组。</p>
<div><iframe class="interactive interactive-js" frameborder="0" height="250" src="https://interactive-examples.mdn.mozilla.net/pages/js/functions-restparameters.html" width="100%"></iframe></div>
<p class="hidden">The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a class="external" href="https://github.com/mdn/interactive-examples" rel="noopener">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
<h2 id="语法">语法</h2>
<pre><code class="language-javascript">function(a, b, ...theArgs) {
// ...
}
</code></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><font face="Open Sans, Arial, sans-serif"></font><code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array/map" title="Array map method">map</a></code><font face="Open Sans, Arial, sans-serif"></font><code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Array/forEach" title="Array forEach method">forEach</a></code><font face="Open Sans, Arial, sans-serif"></font><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></code></pre>
<h3 id="解构剩余参数">解构剩余参数</h3>
<p>剩余参数可以被解构,这意味着他们的数据可以被解包到不同的变量中。请参阅<a href="Reference/Operators/Destructuring_assignment">解构赋值</a></p>
<pre><code class="language-javascript">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)</code></pre>
<h2 id="Example" name="Example">示例</h2>
<p>因为<code>theArgs</code>是个数组,所以你可以使用<code>length</code>属性得到剩余参数的个数:</p>
<pre><code class="language-javascript">function fun1(...theArgs) {
  alert(theArgs.length);
}
 
fun1();  // 弹出 "0", 因为theArgs没有元素
fun1(5); // 弹出 "1", 因为theArgs只有一个元素
fun1(5, 6, 7); // 弹出 "3", 因为theArgs有三个元素</code></pre>
<p>下例中,剩余参数包含了从第二个到最后的所有实参,然后用第一个实参依次乘以它们:</p>
<pre><code class="language-javascript">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]
</code></pre>
<p>下例演示了你可以在剩余参数上使用任意的数组方法,而<code>arguments</code>对象不可以:</p>
<pre><code class="language-javascript">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
</code></pre>
<p>为了在<code>arguments</code>对象上使用<code>Array</code>方法,它必须首先被转换为一个真正的数组。</p>
<pre><code class="language-javascript">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</code></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><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Function Definitions</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition</td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-function-definitions" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Function Definitions</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容">浏览器兼容</h2>
<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><a href="Reference/Functions/rest_parameters">Rest parameters</a></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
47</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
15</td><td class="bc-supports-no bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
34</td><td class="bc-supports-yes bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
10</td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
47</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
47</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
15</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
34</td><td class="bc-supports-yes bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
10</td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
5.0</td><td class="bc-supports-yes bc-browser-nodejs bc-has-history"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
6.0.0<div class="bc-icons"></div><section class="bc-history" id="sect1"><dl><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
6.0.0<div class="bc-icons"></div></dt><dd></dd><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4.0.0<div class="bc-icons"><abbr class="only-icon" title="User must explicitly enable this feature."><span>Disabled</span><i class="ic-disabled"></i></abbr> </div></dt><dd><abbr class="only-icon" title="User must explicitly enable this feature."><span>Disabled</span><i class="ic-disabled"></i></abbr> From version 4.0.0: this feature is behind the <code>--harmony</code> runtime flag.</dd></dl></section></td></tr><tr><th scope="row">Destructuring rest parameters</th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
49</td><td class="bc-supports-no bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
52</td><td class="bc-supports-no bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
36</td><td class="bc-supports-unknown bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr title="Compatibility unknown; please update this.">
?
</abbr></td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
49</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
49</td><td class="bc-supports-no bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-no only-icon" title="No support">
<span>No support</span>
</abbr>
No</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
52</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
36</td><td class="bc-supports-unknown bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr title="Compatibility unknown; please update this.">
?
</abbr></td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
5.0</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td></tr></tbody></table><section class="bc-legend" id="sect2"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
 
</abbr></span></dt><dd>Full support</dd><dt><span class="bc-supports-no bc-supports">
<abbr class="bc-level bc-level-no only-icon" title="No support">
<span>No support</span>
 
</abbr></span></dt><dd>No support</dd><dt><span class="bc-supports-unknown bc-supports">
<abbr class="bc-level bc-level-unknown only-icon" title="Compatibility unknown">
<span>Compatibility unknown</span>
 
</abbr></span></dt><dd>Compatibility unknown</dd><dt><abbr class="only-icon" title="User must explicitly enable this feature."><span>User must explicitly enable this feature.</span><i class="ic-disabled"></i></abbr></dt><dd>User must explicitly enable this feature.</dd></dl></section></div><p></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 class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters" rel="noopener">Original proposal at ecmascript.org</a></li>
<li><a class="external" href="http://javascriptweblog.wordpress.com/2011/01/18/javascripts-arguments-object-and-beyond/" rel="noopener">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>
</article>