函數在被呼叫時執行環境被創造,
同時創造變數環境、外部環境與特殊變數 this 時也會創造變數 arguments
圖片來源:JavaScript 全攻略:克服 JS 的奇怪部分課程第 4 節講座 39 影片截圖
變數 arguments 可以用來得知呼叫函數時傳入哪些參數,
先來看個例子
程式碼如下:
function greet(firstname, lastname, language) {
console.log(firstname);
console.log(lastname);
console.log(language);
}
greet();
在 Console 中的結果如下:
JavaScript 允許我們在呼叫函數時不帶參數(變數),
如果我沒有傳入參數(變數),這些參數在函數呼叫時執行環境的創造階段一樣在記憶體中被設值為 undefined ,
如果我只傳入一個參數,
程式碼如下:
function greet(firstname, lastname, language) {
console.log(firstname);
console.log(lastname);
console.log(language);
console.log('-----------');
}
greet();
greet('John');
在 Console 中的結果如下:
在呼叫函數時有傳入 'John' 所以現在第一個參數有值,其他兩個參數因為都沒有傳值,
所以在函數的執行環境創造階段因為 Hoisting 的原因在記憶體裡被設值為 undefined ,
如果在傳入第2 與第3 個參數呢?
程式碼如下:
function greet(firstname, lastname, language) {
console.log(firstname);
console.log(lastname);
console.log(language);
console.log('-----------');
}
greet('John', 'Doe');
greet('John', 'Doe', 'es');
在 Console 中的結果如下:
參數是從左到右依序傳入的
新版的 JavaScript 可以直接在參數上設值,但要注意瀏覽器的兼容性
程式碼如下:
function greet(firstname, lastname, language = 'en') {
console.log(firstname);
console.log(lastname);
console.log(language);
console.log('-----------');
}
greet('John', 'Doe');
在 Console 中的結果如下:
或是也可以透過預設值的方式來設值,
程式碼如下:
function greet(firstname, lastname, language) {
language = language || 'cn';
console.log(firstname);
console.log(lastname);
console.log(language);
console.log('-----------');
}
greet('John', 'Doe');
在 Console 中的結果如下:
透過這種方式也能替參數設值
現在來看一開始提到的函數被呼叫時執行環境被創造同時替我們創造變數 arguments ,
變數 arguments 能夠儲存所有的參數是一個 Array Like (類似陣列的東西)的資料
程式碼如下:
function greet(firstname, lastname, language) {
console.log(firstname);
console.log(lastname);
console.log(language);
console.log(arguments);
console.log('-----------');
}
greet('John', 'Doe', 'es');
在 Console 中的結果如下:
變數 arguments 被包在一個斜斜的中括號中,而陣列是一般的 [] 運算子, 有些差異,
Array Like 的資料提供一些簡化的陣列屬性與方法,
變數 arguments 可讓我們依據傳入的參數數量來做不同的事,
像是如果沒有傳任何參數就 console.log 出缺少參數的訊息,
程式碼如下:
function greet(firstname, lastname, language) {
if(arguments.length === 0){
console.log('Missing parameters');
console.log('--------');
return; // 程式中斷點, 這邊不會在往下執行呼叫函數
}
console.log(firstname);
console.log(lastname);
console.log(language);
console.log(arguments);
console.log('-----------');
}
greet();
greet('John', 'Doe');
在 Console 中的結果如下:
這樣在呼叫函數沒有傳參數時可以有文字提醒
變數 arguments 的取用方式跟陣列一樣,
程式碼如下:
function greet(firstname, lastname, language) {
if(arguments.length === 0){
console.log('Missing parameters');
console.log('--------');
return;
}
console.log('arg0: ' + arguments[0]);
console.log('-----------');
}
greet('John', 'Doe');
在 Console 中的結果如下:
可以看到如果我們想取用第一個參數
就要像取用陣列一樣
第一個成員從索引值 0 開始
另外在 ES 6 中提出了新的語法,透過 spread 運算子 ,可以方便我們取用參數,
程式碼如下:
function greet(...other) {
console.log(other);
}
greet('John', 'Doe');
在 Console 中的結果如下:
在原來的參數的地方可以透過 spread 運算子 (3個點) 來取得所有的參數,
需注意取得的所有參數是 Array Like 型別,它是類似陣列的東西,在功能上比起陣列少了一些方法,
透過 spread 運算子我們不用把每個參數的名稱都先寫好,
程式碼如下:
function greet(firstname, lastname, language, ...other) {
console.log(other);
}
greet('John', 'Doe', 'es', 'New York', '111 Main St.');
在 Console 中的結果如下:
這樣我們可以取得其他參數而不用預先定義參數的名稱,
雖然 spread 運算子用起來很方便,但還存在著瀏覽器兼容性的問題需要顧慮,你可能會在一些舊的專案中還是會看到透過變數 arguments 來操作參數的作法。