一、前言
1、在函式呼叫的時候,瀏覽器每次都會傳遞進兩個隱式引數:
一個是函式的上下文物件this
,另一個則是封裝實參的類陣列物件arguments
。
2、與其他程式設計語言不同,ECMAScript
不會驗證傳遞給函式的引數個數是否等於函式定義的引數個數。開發者定義的函式都可以接受任意個數的引數(但根據Netscape
的文件,最多可接受255個),而不會引發任何錯誤。任何遺漏的引數都會以undefined
傳遞給函式,多餘的函式將忽略。
即引數從左向右進行匹配,如果實參個數少於形參,後面的引數對應賦值為undefined
。如:
function fn (a, b, c) {
console.log(a, b, c); // 1 2 undefined
// 函式物件的length屬性就是函式形參的個數
console.log(fn.length); // 3
}
fn(1, 2);
複製程式碼
二、arguments
1、描述
arguments
的定義是物件,但是因為物件的屬性是無序的,而arguments
是用來儲存實參的,是有順序的,它具備和陣列相同的訪問性質及方式,並擁有陣列長度屬性length
,所以arguments
是特殊的物件,又叫類陣列物件,當我們聽到類陣列時就可以知道說的是arguments
。
即arguments
是一個類陣列物件,用來儲存實際傳遞給函式的引數,使呼叫函式時不侷限於函式宣告所定義的引數列表。
function fn() {
console.log(arguments);
console.log(typeof arguments); // object
console.log(toString.call(arguments)); // [object Arguments]
}
fn('name', 'age');
複製程式碼
2、訪問實參和檢查實參個數
arguments
訪問單個引數的方式與訪問陣列元素的方式相同。例如arguments[0]
、arguments[1]
、arguments[n]
,在函式中不需要明確指出引數名,就能訪問它們。通過length
屬性可以知道實參的個數。
function f2() {
console.log(arguments[0]); // name
console.log(arguments[1]); // age
console.log(arguments.length); // 2
}
f2('name', 'age');
複製程式碼
3、callee屬性
每一個物件都有自己的屬性,而arguments
有一個callee
屬性,返回正被執行的Function
物件。
function f3() {
console.log(arguments.callee === f3); // true
}
f3('name', 'age');
複製程式碼
4、arguments的修改
在正常的模式下,arguments
物件是允許在執行時進行修改的。
function f4() {
arguments[0] = 'sex';
console.log(arguments[0]); // sex
}
f4('name', 'age');
複製程式碼
5、轉化成真實陣列
arguments
是類陣列物件,除了length
屬性和索引元素之外沒有任何Array
屬性。例如,它沒有 pop
方法。但是它可以被轉換為一個真正的Array
:
function f5(){
// 可以使用slice來將arguments轉換為真實陣列
var args1 = Array.prototype.slice.call(arguments);
var args2 = [].slice.call(arguments);
// 也可以使用Array.from()方法或者擴充套件運算子來將arguments轉換為真實陣列
var args3 = Array.from(arguments);
var args4 = [...arguments];
}
f5('name', 'age');
複製程式碼
三、應用
1、借用arguments.length
可以來檢視實參和形參的個數是否一致
function fn (a, b, c) {
if (fn.length != arguments.length) {
console.log('形參和實參的個數不一致');
} else{
console.log('形參和實參的個數一致');
}
}
fn(1, 2);
複製程式碼
2、借用arguments.callee
來讓匿名函式實現遞迴:
let sum = function (n) {
if (n == 1) {
return 1;
} else {
return n + arguments.callee(n - 1); // 5 4 3 2 1
}
}
console.log(sum(6)); // 21
複製程式碼
3、遍歷引數求和或者求最大值
function max () {
var max = arguments[0];
for (item of arguments) {
if (item > max) {
max = item;
}
}
return max;
}
console.log(max(5, 3, 2, 9, 4)); // 9
複製程式碼
4、模擬函式過載
過載函式是函式的一種特殊情況,為方便使用,C++
允許在同一範圍中宣告幾個功能類似的同名函式,但是這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同,也就是說用同一個函式完成不同的功能。
用arguments
物件判斷傳遞給函式的引數個數,即可模擬函式過載:
function doAdd() {
if(arguments.length == 1) {
console.log(arguments[0] + 5);
} else if(arguments.length == 2) {
console.log(arguments[0] + arguments[1]);
}
}
doAdd(10); // 15
doAdd(10, 20); // 30
複製程式碼
四、總結
1、arguments
是一個類陣列物件,用來儲存實參;具有length
、callee
等屬性;可以用arguments[0]
這個形式訪問實參;可以轉換為真實陣列。
2、arguments
和函式相關聯,其只有在函式執行時可用,不能顯式建立。
3、arguments
可以用來遍歷引數;通過callee
實現遞迴;也可以模擬函式過載。