2012-08-07 16 views
3

介紹原型 「論據」

大家都知道的JavaScript函數這些無聊的arguments對象。

但爲什麼是對象?它不是一個數組?

不,這不是,這就是爲什麼很多人把它JavaScript中概念的失敗:

(function() { 
    return arguments.slice(); // TypeError: arguments.slice is not a function 
}()); 

意向

好吧,這只是介紹了實際我想問的事情,但在問你需要一些更多的信息之前:

在最後幾天閱讀不同的代碼時,我在相當多的地方看到下面的代碼行時非常尷尬。

args = Array.prototype.slice(arguments); 

那麼,這是什麼做的,僅僅是「轉化」的arguments對象到一個數組與所有的原型和東西。


我的解決方案

我想起了什麼是以下幾點:雖然JavaScript是所有關於原型,我們爲什麼不延長arguments對象的prototype本身?我查了一些網站的現有腳本,但一無所獲,我打算找,終於把它寫自己:

(function() { 
    var i, methods; 

    arguments.constructor.prototype = Array.prototype; 
    methods = ['concat', 'join', 'pop', 'push', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'unshift']; 

    for (i = 0; i < methods.length; i += 1) { 
     if (arguments.constructor.prototype.hasOwnProperty(methods[i]) === false) { 
      arguments.constructor.prototype[methods[i]] = Array.prototype[methods[i]]; 
     } 
    } 
}()); 

壓縮後只需要260字節,延長使用Array.prototypearguments對象的prototype

因此,最後我可以處理arguments對象,就像「真正」的數組一樣。


問題

檢查最著名的JavaScript框架我有以下完成後:沒有使用這樣的構建和擴展arguments對象的prototype

但是爲什麼?有什麼不對嗎,我現在沒有想到?

回答

5

arguments對象不是一個類型,它是一個通用的Object。爲了擴展它的原型,你將不得不擴展原型Object,這通常不是一個好主意。

使用Array.prototype.slicearguments轉換爲數組沒有任何問題。

比方說,我是延長arguments原型:

arguments.constructor.prototype.foo = 'bar'; 

的這裏的問題是,arguments.constructor是不是有些Argument對象,它只是Object。現在,如果我嘗試做一些事情,應該正常工作,它fubar'd:

var someNewObject = { 
    someProperty: 'someValue' 
}; 

for (var item in someNewObject) { 
    console.log(item); // logs someProperty AND foo, not good 
} 

您可以在行動here看到這一點。

+0

其實你是對的,沒有注意到。這正是我一直在尋找的......呃,有時候這只是一些可以忘記考慮的事情... – 2012-08-07 17:46:00

+0

這也是一個(除了表現之外)爲什麼迭代整數for循環優先於for-循環中。雖然可以在for-in中使用.hasOwnProperty()方法,但由於增強的本機對象(特別是Array對象)的潛力,通常不安全。 – 2012-08-08 02:25:15

+0

@ say2joe for-in循環用於對象,for循環用於其他所有內容。 – jbabey 2012-08-08 12:29:48

2

一般來說,大多數人迴避更改ECMAScript/JavaScript本機對象。就我個人而言,我喜歡你的方法(它很聰明和有用);但是,當您將代碼引入較大的項目時會引入問題。當瀏覽器的Array(native)對象的實現與標準和其他代碼庫(如jQuery)不同時,可能會產生意想不到的後果,從而對某些期望產生影響。但是,如果jQuery希望某個函數的參數屬性(/ object)具有某種特定類型,並且已被更改(例如通過代碼),那麼您可能會很好地分解一個廣泛使用的庫,如jQuery。

0

它工作嗎? ;-)

如果是這樣,我認爲你已經達到了你想要的。然而,參數不是數組的一個原因可能是參數變量不能像普通變量那樣傳播。它只能在函數體內被訪問,然後被拋棄。因此我不知道會發生什麼,當它突然一個數組。

除此之外,聰明的解決方案!