JS arguments物件詳解(附帶多個範例)

2020-07-16 10:05:03
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]