首頁 >web前端 >js教程 >JavaScript進階系列—arguments 物件

JavaScript進階系列—arguments 物件

黄舟
黄舟原創
2017-02-08 09:43:551138瀏覽
  • 轉換為陣列

  • 傳遞參數

  • 自動更新

  • 效能中一個特別變數

  • Script

效能中一個特別變數這個變數維護著所有傳遞到這個函數中的參數列表。

arguments 變數不是一個陣列(Array)。 儘管在語法上它有數組相關的屬性 length,但它不從 Array.prototype 繼承,實際上它是一個物件(Object)。

(注意: 由於arguments 已經被定義為函數內的一個變數。 因此透過var 關鍵字定義arguments 或將arguments 宣告為一個形式參數, 都會導致原生的arguments 不會被建立。)

因此,無法對arguments 變數使用標準的陣列方法,例如push, pop 或slice。 雖然使用 for 迴圈遍歷也是可以的,但是為了更好的使用陣列方法,最好把它轉換為真正的陣列。

轉換為數組

下面的程式碼將會建立一個新的數組,包含所有 arguments 物件中的元素。

Array.prototype.slice.call(arguments);

這個轉換比較慢,在效能不好的程式碼中不推薦這種做法。

傳遞參數

下面是將參數從一個函數傳遞到另一個函數的建議做法。

function foo() {
    bar.apply(null, arguments);
}
function bar(a, b, c) {
    // 干活
}

另一個技巧是同時使用 call 和 apply,創建一個快速的解綁定包裝器。

function Foo() {}

Foo.prototype.method = function(a, b, c) {
    console.log(this, a, b, c);
};

// 创建一个解绑定的 "method"
// 输入参数为: this, arg1, arg2...argN
Foo.method = function() {

    // 结果: Foo.prototype.method.call(this, arg1, arg2... argN)
    Function.call.apply(Foo.prototype.method, arguments);
};

譯者註:上面的 Foo.method 函數和下面程式碼的效果是一樣的:

Foo.method = function() {
    var args = Array.prototype.slice.call(arguments);
    Foo.prototype.method.apply(args[0], args.slice(1));
}

自動更新

arguments 物件為其內部屬性以及函數形式參數建立 getter 和 setter 方法。

因此,改變形參的值會影響到 arguments 物件的值,反之亦然。

function foo(a, b, c) {
    arguments[0] = 2;
    a; // 2                                                           

    b = 4;
    arguments[1]; // 4

    var d = c;
    d = 9;
    c; // 3
}
foo(1, 2, 3)

性能真相

不管它是否有被使用,arguments 物件總是會被創建,除了兩個特殊情況 - 作為局部變數聲明和作為形式參數。

arguments 的 getters 和 setters 方法總是會被創建;因此使用 arguments 對效能不會有什麼影響。 除非是需要對 arguments 物件的屬性進行多次存取。

譯者註:在 MDC 中對 strict mode 模式下 arguments 的描述有助於我們的理解,請看下面代碼:

// 阐述在 ES5 的严格模式下 `arguments` 的特性
function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);

然而,的確有一種情況會顯著的影響現代 JavaScript 引擎的性能。這就是使用arguments.callee。

function foo() {
    arguments.callee; // do something with this function object
    arguments.callee.caller; // and the calling function object
}

function bigLoop() {
    for(var i = 0; i < 100000; i++) {
        foo(); // Would normally be inlined...
    }
}

上面程式碼中,foo 不再是一個單純的內聯函數 inlining(譯者註:這裡指的是解析器可以做內聯處理), 因為它需要知道它自己和它的調用者。 這不僅抵消了內聯函數帶來的效能提升,而且破壞了封裝,因此現在函數可能要依賴特定的上下文。

因此強烈建議大家不要使用 arguments.callee 和它的屬性。

以上就是JavaScript進階系列—arguments 物件的內容,更多相關內容請關注PHP中文網(www.php.cn)!

🎜🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn