[JavaScriptWeird]No.30 arguments 與其餘參數

當我們呼叫執行函式時,其實 JavaScript 不只建立了特殊的關鍵字 this ,還建立了特殊關鍵字 arguments ,以及 ES6 後新增的其餘參數。

參數 (arguments)

如同開頭所說的,當新的執行環境被創造,然後 JavaScript 會幫我們設定一些東西,像是用變數環境包住變數給範圍鏈的外部程式參考、以及特殊關鍵字 thisarguments

arguments 包含了所有傳入函式的參數

課程截圖
課程截圖

從範例了解 arguments 是什麼:

1
2
3
4
5
6
function greet(firstName, lastName, languaue){  
console.log(firstName);
console.log(lastName);
console.log(languaue);
}
greet();

JavaScript 與其他程式語言一個很不同的地方是,假使我們寫了一個需要帶參數的函式,呼叫函式時如果不帶任何參數也可以執行。在其他語言這樣會發生錯誤,但 JavaScript 不會,這是因為 JavaScript 具有提升的效果。

然而在 ES6 中,我們甚至可以使用預設參數的技巧,讓函式的參數有預設值,這些之前就示範過了,因此不再贅述。

慢慢將參數傳入函式觀察變化

1
2
3
4
5
6
7
function greet(firstName, lastName, languaue){  
console.log(firstName);
console.log(lastName);
console.log(languaue);
}
greet();
greet('John');

像這樣,僅傳入對應 firstName 變數的參數值,

繼續傳入其他參數,

1
2
3
4
5
6
7
8
9
function greet(firstName, lastName, languaue){  
console.log(firstName);
console.log(lastName);
console.log(languaue);
}
greet();
greet('John');
greet('John', 'Doe');
greet('John','Doe','es');

透過這樣的實驗,表示我們可以省略傳入參數也不會發生錯誤 (Error),或者是可以只傳入一部分的參數。

arguments 是類陣列

什麼是類陣列 (array-like),簡單來說,這是個長的像陣列的東西,但是它不支援部分陣列的方法。

1
2
3
4
5
6
7
8
9
10
11
function greet(firstName, lastName, languaue){  
console.log(firstName);
console.log(lastName);
console.log(languaue);
console.log(arguments);
console.log('-----------');
var arr = \[1,2,3\];
console.log(arr);
}

greet('John','Doe','es');


我並沒有宣告 arguments ,但我卻可以使用,這是因為當函式執行時, arguments 就與 this 一同被創造了。

然而如同上面所述,類陣列因為不是真正的陣列,所以相較真正的陣列而言少了很多能用的方法,可觀察 __proto__ 底下的得知。

也可以觀察到 arguments 包含了所有傳入的參數值,因此可以像取用一般陣列的值一樣地使用 arguments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function greet(firstName, lastName, languaue){  
if (arguments.length === 0){
console.log('沒有傳入參數');
return;
}
console.log(firstName);
console.log(lastName);
console.log(languaue);
console.log(arguments);
console.log(arguments[2]);
console.log('-----------');
var arr = [1,2,3];
console.log(arr);
}
greet();
greet('John','Doe','es');

像是我們可以利用 arguments 來判斷函式有沒有傳入參數,或者取出特定索引的值等等運用。

隨著 JavaScript 的發展,在 ES6 中,我們可以使用其餘參數來取代 arguments ,但不代表 arguments 不存在了,它仍然可以使用,只是有更好的選擇。

其餘參數 (Rest parameters)

詳細可以參考這篇課外讀物

簡單來說如果我們有傳入函式的參數,可以使用「…」來省略,但要特別注意的是,只能在沒有其他參數下,或者「…」必須是最後一個參數才可以使用。

其餘參數比起 arguments 好用的地方在於,其餘參數是一個真正的陣列,支援所有可以用於陣列上的方法, arguments 是類陣列,處理上較為麻煩。

1
2
3
4
5
6
7
8
9
10
11
function greet(firstName, lastName, languaue, ...other){  
if (arguments.length === 0){
console.log('沒有傳入參數');
return;
}
console.log(arguments);
console.log(other);
console.log('-----------');
}
greet();
greet('John','Doe','es','orther1','orther2','orther3');


而比較典型的例子像是這個:

計算加總 — 其餘參數

1
2
3
4
5
6
7
8
9
function sum(...input) {  
var result = 0;
input.forEach(function(input) {
result += input;
});
return result;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3, 4, 5)); // 15

由於其餘參數會回傳一個真正的陣列,所以可以使用陣列方法來計算,程式碼相對的易讀明瞭。

計算加總 — arguments

1
2
3
4
5
6
7
8
9
function sum() {  
var result = 0;
for (var i = 0;i<arguments.length;i++){
result += arguments[i]
}
return result;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3, 4, 5)); // 15

雖然 arguments 也能做到一樣的事情,但是因為不是真正的陣列,沒辦法使用 ES6 新增的一些好用的陣列方法,所以只能使用 for 迴圈一個個加總,或者使用其他方式將類陣列轉換成真正的陣列。

也因為 arguments 不能自訂一個名稱,所以也很難讓人明白到底這段程式是在做些什麼。

0%