2014-02-10 57 views
0

這是我嘗試擴展本地數組對象,長度可枚舉嗎?

var extend = function(base, sub) { 
    sub.prototype = Object.create(base.prototype); 
    sub.prototype.constructor = sub; 
}; 

MyArray = function() { 
    Array.call(this, arguments); 
}; 

extend(Array, MyArray); 

var arr = new MyArray(); 

arr.push(1); 
arr.push(2); 
arr.push(3); 

console.log(arr); 

for (var i in arr) { 
    if (arr.hasOwnProperty(i)) { 
     console.log(i + " => " + arr[i]); 
    } 
} 

而且它產生的輸出(在節點運行此)

{ '0': 1, '1': 2, '2': 3, length: 3 } 
0 => 1 
1 => 2 
2 => 3 
length => 3 

我想通過調用Array.call(this, arguments)

我會被假冒的建設對象到本地構造函數,它應該處理不可枚舉的長度。

當切換到new Array()時,它會生成以下輸出。

[ 1, 2, 3 ] 
0 => 1 
1 => 2 
2 => 3 

一般問題是爲什麼在結果對象中的差異,更具體地說,爲什麼是可以枚舉的長度屬性?

+0

擴展本地數組非常麻煩。如果你可以在你的MyArray類中封裝一個數組,它會容易得多。 – Tibos

+1

當然,這是一個稍微學術化的問題來定義「麻煩大家」的含義。 – jondavidjohn

回答

2

我假設通過調用Array.call(this, arguments)我會將對象的構造傳遞給本地構造函數,該構造函數應該處理不可枚舉的長度。

編號EcmaScript 5 does not allow to subclass Array - 在像節點這樣的受控環境中,您只能使用var arr=[]; arr.__proto__=mycustomprototype;黑客。

Array.call(this)不幸的是不起作用。它返回一個新的數組,它不分配任何東西,但它不會對this執行任何操作。您可以通過this !== Array.call(this)進行檢查。

那麼你是如何得到你的自定義對象的length屬性? push確實創建了它。它看到了繼承的Array.prototype.length屬性(0),所以在插入數字後它分配了arr.length = 1,它創建了一個枚舉屬性。

+0

質量鏈接,並感謝您的解釋。 – jondavidjohn

0

一般來說,避免從標準類繼承是一種很好的做法。原因是有一些屬性,例如長度,特別是對內部標記爲真數組的對象進行操作。

使用Array構造函數或數組文字表達式創建的對象將該內部屬性設置爲「Array」。 Array子類的實例具有[[Class]]屬性的「Object」值。請嘗試以下

Object.prototype.toString.call(arr); // "[object Object]" 

Object.prototype.toString.call([]); // "[object Array]" 

這意味着,某些陣列屬性將失去它們的默認行爲。