arguments 物件表示函數的實參集合,僅能夠在函數體內可見,並可以直接存取。
arguments 物件的 length 屬性和 callee 屬性最為常用:
-
使用 length 屬性可以獲取函數的實參個數。arguments 物件只能在函數體內可見,因此 arguments.length 也只能在函數體內使用。
-
使用 callee 屬性可以參照當前 arguments 物件所在的函數。使用 callee 屬性可以在函數體內呼叫函數自身。在匿名函數中,callee 屬性比較有用。例如,利用它可以設計遞回呼叫。
【範例1】獲取實參和形參的個數
使用 arguments.length 屬性可以獲取函數的實參個數。使用函數物件的 length 屬性可以獲取函數的形參個數,該屬性為唯讀屬性,在函數體內、體外都可以使用。
下面範例設計一個 checkArg() 函數,用來檢測一個函數的形參和實參是否一致,如果不一致則丟擲異常。
function checkArg(a) { //檢測函數實參與形參是否一致
if (a.length != a.callee.length) //如果實參與形參個數不同,則丟擲錯誤
throw new Error("實參和形參不一致");
}
function f(a, b) { //求兩個數的平均值
checkArg(arguments); //根據arguments來檢測函數實參和形參是否一致
return ((a * 1 ? a : 0) + (b * 1 ? b : 0)) / 2; //返回平均值
}
console.log(f(6)); //丟擲異常。呼叫函數f,傳入一個引數
【範例2】遍歷函數實參
在下面範例中,函數沒有定義形參,但是在函數體內通過 arguments 物件可以獲取呼叫函數時傳入的每一個值。
function f() { //定義沒有形參的函數
for (var i = 0; i < arguments.length; i ++) { //遍歷arguments物件
console.log(arguments[i]); //顯示指定下標的實參的值
}
}
f(3, 3, 6); //逐個顯示傳遞的實參
arguments 物件是一個偽類陣列,不能夠繼承 Array 的原型方法。可以使用陣列下標的形式存取每個實參,如 arguments[0] 表示第一個實參。下標值從 0 開始,直到 arguments.length-1。其中 length 是 arguments 物件的屬性,表示函數包含的實參個數。同時,arguments 物件允許更新其包含內容的實參值。
【範例3】在函數內部修改實參的值
在下面範例中使用 for 迴圈遍歷 arguments 物件,然後把迴圈變數的值傳入 arguments,以便於改變實參值。
function f() {
for (var i = 0; i < arguments.length; i++) { //遍歷arguments物件
arguments[i] = i; //修改每個實參的值
console.log(arguments[i]); //提示修改的實參值
}
}
f(3, 3, 6); //返回提示0、1、2,而不是3、3、6
【範例4】改變函數實參的個數
通過修改 length 屬性值,也可以改變函數的實參個數。當 length 屬性值增大時,則增加的實參值為 undefined;如果 length 屬性值減小,則會丟棄 length 長度值之後的實參值。
function f() {
arguments.length = 2; //修改arguments屬性物件的length屬性值
for (var i = 0; i < arguments.length; i ++) {
console.log(arguments[i]);
}
}
f(3, 3, 6); //返回提示3、3
【範例5】檢測使用者傳遞的引數是否符合要求
在下面範例中,使用 arguments.callee 獲取匿名函數,然後通過函數的 length 屬性獲取函數形參個數,最後比較實參個數與形參個數,以檢測使用者傳遞的引數是否符合要求。
function f(x,y,z) {
var a = arguments.length(); //獲取函數實參的個數
var b = arguments.callee.length; //獲取函數形參的個數
if (a != b_ { //如果實參和形參個數不相等,則提示錯誤資訊
throw new Error("傳遞的引數不匹配");
}else { //如果實參和形參個數相同,則返回它們的和
return x + y + z;
}
}
console.log(f(3,4,5)); //返回值12
arguments.callee 等價於函數名,在上面範例中,arguments.callee 等於 f。
再談 arguments 物件的應用
在實際開發中,arguments 物件非常有用。靈活使用 arguments 物件,可以提升使用函數的靈活性,增強函數在抽象程式設計中的適應能力和糾錯能力。下面結合幾個典型範例展示 arguments 的應用。
1) 使用 arguments 物件能夠增強函數應用的靈活性。例如,如果函數的引數個數不確定,或者函數的引數個數很多,而又不想逐一定義每一個形參,則可以省略定義引數,直接在函數體內使用 arguments 物件來存取呼叫函數的實參值。
範例1
下面範例定義一個求平均值的函數,該函數借助 arguments 物件來計算引數的平均值。在呼叫函數時,可以傳入任意多個引數。
function avg() { //求平均值
var num = 0, 1 = 0; //宣告並初始化臨時變數
for (var i = 0; i < arguments.length; i ++) { //遍歷所有實參
if (typeof arguments[i] != "number") //如果引數不是數值
continue; //則忽略該引數值
num += arguments[i]; //計算引數的數值之和
1 ++; //計算參與和運算的引數個數
}
num /= 1; //求平均值
return num; //返回平均值
}
console.log(avg(1,2,3,4)); //返回2.5
console.log(avg(1,2,"3",4)); //返回2.3333333333333335
範例2
在頁面設計中經常需要驗證表單輸入值,下面範例檢測文字方塊輸入的值是否為合法的郵箱地址。
function isEmail() {
if (arguments.length > 1) throw new Error("只能夠傳遞一個引數"); //檢測引數個數
var regexp = /^w+((-w+) | (.w+)) *@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+)8.[A-Za-z0-9]+$/; //定義正規表示式
if (arguments[0].search(regexp) != -1) //匹配實參的值
return true; //如果匹配則返回true
else
return false; //如果不匹配則返回false
}
var email = "[email protected]"; //宣告並初始化郵箱地址字串
console.log(isEmail(email)); //返回true
2) arguments 物件是偽類陣列,不是陣列,可以通過 length 屬性和中括號語法來遍歷或存取實參的值。不過,通過動態呼叫的方法,也可以使用陣列的方法,如 push、pop、slice 等。
範例3
使用 arguments 可以模擬過載。實現方法:通過 arguments.length 屬性值判斷實際引數的個數和型別,決定執行不同的程式碼。
function sayHello() {
switch(arguments.length) {
case 0 :
return "Hello";
case 1 :
return "Hello, " + arguments[0];
case 2 :
return (arguments[1] == "cn" ? "你好, " : "Hello, ") + arguments[0];
};
}
console.log(sayHello()); //"Hello"
console.log(sayHello("Alex")); //"Hello,Alex"
console.log(sayHello("Alex", "vn")); //"你好,Alex"
範例4
下面範例使用動態呼叫的方法,讓 arguments 物件呼叫陣列方法 slice(),可以把函數的引數物件轉換為陣列。
function f() {
return [].slice.apply(arguments);
}
console.log(f(1,2,3,4,5,6)); //返回[1,2,3,4,5,6]