ES6+ 剩余參數(shù)
1. 前言
上節(jié)我們學(xué)習(xí)了展開(kāi)語(yǔ)法,本節(jié)我們學(xué)習(xí)與之相反的操作 —— 剩余語(yǔ)法(Rest syntax 也可以叫剩余參數(shù))看起來(lái)和展開(kāi)語(yǔ)法完全相同都是使用 ...
的語(yǔ)法糖,不同之處在于剩余參數(shù)用于解構(gòu)數(shù)組和對(duì)象。從某種意義上說(shuō),剩余語(yǔ)法與展開(kāi)語(yǔ)法是相反的:展開(kāi)語(yǔ)法將數(shù)組展開(kāi)為其中的各個(gè)元素,而剩余語(yǔ)法則是將多個(gè)元素收集起來(lái)成為一個(gè)整體。
2. 函數(shù)參數(shù)
在講解剩余參數(shù)前,我們先來(lái)看看,剩余參數(shù)在函數(shù)參數(shù)中都解決了哪些問(wèn)題?為什么會(huì)引入剩余參數(shù)的概念?
在 ES5 中,函數(shù)經(jīng)常會(huì)傳入不定參數(shù),在傳入不定參數(shù)時(shí),ES5 的給出的解決方案是通過(guò) arguments
對(duì)象來(lái)獲取函數(shù)調(diào)用時(shí)傳遞的參數(shù)。 arguments
對(duì)象不是一個(gè)數(shù)組,它是一個(gè)類(lèi)數(shù)組對(duì)象,所謂類(lèi)數(shù)組對(duì)象,就是指可以通過(guò)索引屬性訪問(wèn)元素并且擁有 length 屬性的對(duì)象。
一個(gè)簡(jiǎn)單的類(lèi)數(shù)組對(duì)象是長(zhǎng)這樣的:
var arrLike = {
0: 'name',
1: 'age',
2: 'job',
length: 3
}
而它所對(duì)應(yīng)的數(shù)組應(yīng)該是這樣子的:
var arr = ['name', 'age', 'job'];
這里我們說(shuō)類(lèi)數(shù)組對(duì)象與數(shù)組的性質(zhì)相似,是因?yàn)轭?lèi)數(shù)組對(duì)象在訪問(wèn)、賦值、獲取長(zhǎng)度上的操作與數(shù)組是一致的,具體內(nèi)容可查閱相關(guān)的類(lèi)數(shù)組使用。
在函數(shù)體中定義了 Arguments 對(duì)象,其包含函數(shù)的參數(shù)和其它屬性,以 arguments
變量來(lái)指代。下面我們看個(gè)實(shí)例:
function fn() {
console.log(arguments);
}
fn('imooc', 7, 'ES6')
在控制臺(tái)中打印出上面的代碼結(jié)果,如下圖所示:在定義函數(shù)的時(shí)候沒(méi)有給定參數(shù),但是通過(guò) arguments
對(duì)象可以拿到傳入的參數(shù)??梢钥吹?arguments
中包含了函數(shù)傳遞的參數(shù)、length 等屬性,length 屬性表示的是實(shí)參的長(zhǎng)度,即調(diào)用函數(shù)的時(shí)候傳入的參數(shù)個(gè)數(shù)。這樣我們就對(duì) arguments
對(duì)象有了一定的了解。
在 ES5 的開(kāi)發(fā)模式下,想要使用傳遞的參數(shù),則需要按位置把對(duì)應(yīng)的參數(shù)取出來(lái)。盡管 arguments
是一個(gè)類(lèi)數(shù)組且可遍歷的變量,但它終究不是數(shù)組,它不支持?jǐn)?shù)組方法,因此我們不能調(diào)用 arguments.forEeach (…)
等數(shù)組的方法。需要使用一些特殊的方法轉(zhuǎn)換成數(shù)組使用,如:
function fn() {
var arr = [].slice.call(arguments);
console.log(arr)
}
fn('ES6');
// ["ES6"]
fn('imooc', 7, 'ES6');
// ["imooc", 7, "ES6"]
終于借助 call
方法把 arguments
轉(zhuǎn)化成一個(gè)真正的數(shù)組了。但是這樣無(wú)疑是一個(gè)繁瑣的過(guò)程,而且不容易理解。這時(shí) ES6 給出了它的完美解決方案 —— 剩余參數(shù),那剩余參數(shù)是如何在函數(shù)傳參中使用的呢?下面我們來(lái)看看實(shí)例:
function fn(...args) {
console.log(args)
}
fn('ES6');
// ["ES6"]
fn('imooc', 7, 'ES6');
// ["imooc", 7, "ES6"]
使用方式很簡(jiǎn)單在函數(shù)定義時(shí)使用 ...
緊接著跟一個(gè)收集的參數(shù),這個(gè)收集的參數(shù)就是我們所傳入不定參數(shù)的集合 —— 也就是數(shù)組。這樣就很簡(jiǎn)單地?cái)[脫了 arguments 的束縛。另外,還可以指定一個(gè)默認(rèn)的參數(shù),如下示例:
function fn(name, ...args) {
console.log(name); // 基礎(chǔ)參數(shù)
console.log(args); // 剩下的參數(shù)組成的數(shù)組
}
fn('ES6');
// 'ES6'
// []
fn('imooc', 7, 'ES6');
// "imooc"
// [7, "ES6"]
上面的代碼中給函數(shù)第一個(gè)參數(shù),聲明一個(gè)變量 name,剩余的參數(shù)會(huì)被 ...
收集成一個(gè)數(shù)組,這就是剩余參數(shù)。引入剩余參數(shù)就是為了能替代函數(shù)內(nèi)部的 arguments
,由于 arguments
對(duì)象不具備數(shù)組的方法,所以很多時(shí)候在使用之前要先轉(zhuǎn)換成一個(gè)數(shù)組。而剩余參數(shù)本來(lái)就是一個(gè)數(shù)組,避免了這多余的一步,使用起來(lái)既優(yōu)雅又自然。
2. 解構(gòu)剩余參數(shù)
ES6 允許按照一定模式,從數(shù)組和對(duì)象中提取值,并對(duì)變量進(jìn)行賦值,這被稱(chēng)為解構(gòu)(下節(jié)我們會(huì)講到)。 比如如下代碼:
let array = [1, 2, 3]
let [a, b, c] = array;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
再比如如下代碼:
let obj = {a:1, b:2, c:3}
let {a, b, c} = obj;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
上面的兩個(gè)例子,就是數(shù)組和對(duì)象的解構(gòu)賦值過(guò)程,在解構(gòu)賦值時(shí),可以使用剩余操作符。剩余操作符所操作的變量會(huì)匹配在解構(gòu)賦值中所有其他變量未匹配到的屬性??慈缦率纠?/p>
let {a, b, ...others } = {a: 1, b: 2, c: 3, d: 4, e: 5}
console.log(a); // 1
console.log(b); // 2
console.log(others); // {c: 3, d: 4, e: 5}
上面的代碼中,a、b 會(huì)匹配對(duì)象中對(duì)應(yīng)的值,...others
則會(huì)收集匹配余下的屬性值,并打包起來(lái)構(gòu)造一個(gè)新的對(duì)象賦值給了 others
。
數(shù)組也可以通過(guò)剩余操作符,把剩余的元素打包成一個(gè)新的數(shù)組賦值給剩余屬性,代碼如下:
let array = [1, 2, 3, 4, 5];
let [a, b, ...others] = array;
console.log(a); // 1
console.log(b); // 2
console.log(others); // [3,4,5]
在函數(shù)傳參的時(shí)候也可以是和解構(gòu)一起使用。如下所示。
function fun(...[a, b, c]) {
return a + b + c;
}
fun('1') // NaN (b 和 c 都是 undefined)
fun(1, 2, 3) // 6
fun(1, 2, 3, 4) // 6 多余的參數(shù)不會(huì)被獲取到
上面的代碼中,a、b、c 會(huì)去解構(gòu)傳入?yún)?shù),加上有剩余語(yǔ)法的作用,對(duì)應(yīng)的值從數(shù)組中的項(xiàng)解構(gòu)出來(lái),在函數(shù)內(nèi)部直接使用解構(gòu)出來(lái)的參數(shù)即可。剩余語(yǔ)法看起來(lái)和展開(kāi)語(yǔ)法完全相同,不同點(diǎn)在于,剩余參數(shù)用于解構(gòu)數(shù)組和對(duì)象。
3. 小結(jié)
本節(jié)結(jié)合了 ES5 函數(shù)中的 arguments
對(duì)象引入了為什么 ES6 會(huì)引入剩余參數(shù)的概念,可以看到剩余參數(shù)所帶來(lái)的好處。本節(jié)內(nèi)容可以總結(jié)以下幾點(diǎn):
- 剩余參數(shù)是為了能替代函數(shù)內(nèi)部的 arguments 而引入的;
- 和展開(kāi)語(yǔ)法相反,剩余參數(shù)是將多個(gè)單個(gè)元素聚集起來(lái)形成一個(gè)單獨(dú)的個(gè)體的過(guò)程。