JS的arguments

百聞一見發表於2019-11-16

一、前言

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');
複製程式碼

JS的arguments

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是一個類陣列物件,用來儲存實參;具有lengthcallee等屬性;可以用arguments[0]這個形式訪問實參;可以轉換為真實陣列。

2、arguments和函式相關聯,其只有在函式執行時可用,不能顯式建立。

3、arguments可以用來遍歷引數;通過callee實現遞迴;也可以模擬函式過載。

相關文章