2011-11-24 64 views
2

我可以安全地擴展Javascript builtin類,如Array嗎?我可以安全地擴展JavaScript內置類嗎?

I.e.以下瀏覽器/環境將無法正常工作:

Array.prototype.double = function() { return this.concat(this); } 
Array.twice = function(a) { return a.double(); } 
Array.twice([1, 2, 3]) # => [1, 2, 3, 1, 2, 3] 
+1

這是一種常見的做法,我相信它會在任何地方工作。儘管我不會作爲答覆發佈,因爲其他人可能能夠確定它永遠不會導致您的問題。 –

+0

@Michael只是補充說Object.prototype是唯一一個不受限制的。任何使用'for..in'循環數組的人都應該被絆倒。我不會添加答案,因爲我無法在所有瀏覽器上進行測試。 – Esailija

+0

關於此主題的Andrew Dupont [給出了一個很好的JSConf演示文稿](http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542)。 – Pointy

回答

4

取決於您對「工作」的定義。

原型擴展有三個主要問題。

  • 它是全球範圍,從而有名稱衝突
  • 如果您添加枚舉的屬性它打破for .. in
  • 代碼是混亂閱讀,這是一個ES5功能或自定義庫?

它可以工作,Array.prototypeArray是可變的,所以你可以添加代碼並調用屬性。

然而:

Array.prototype.trolls = 42; 
for (var k in []) { 
    alert(k === "trolls"); 
} 

以上是它打破for .. in的一個例子。這很容易用解決

Object.defineProperty(Array.prototype, "trolls", { 
    value: ..., 
    enumerable: false 
}); 

(ES5僅。在IE <符9.不能在傳統的發動機中模擬)

for (var k in []) { 
    if ([].hasOwnProperty(k)) { 
    alert(k === "trolls"); 
    } 
} 

我個人避免自動延伸當地人這些確切的原因。但是我認爲這是完全可以接受的有.extendNatives函數庫中的像pd.extendNatives

+0

+1 @Raynos我們可以隨時指望您獲得出色的JavaScript解答。 –

+0

[Sugar.js](http://sugarjs.com/)專業。我認爲它可以在受控環境(即您自己的Web應用程序)中受益,並且如果在圖書館中正確使用它也是可以接受的。 – Tomalak

+1

@Tomalak拓展土着不是「壞」的。我默認情況下會這樣做,最好放在'extendNatives'函數後面。如果你的庫不是原生的對象擴展庫,我認爲在庫中做這件事是不可接受的。作爲庫中的副作用擴展本地對象是不好的。擴展本地對象作爲副作用的唯一可能情況是,如果它們填充ES5規範的一部分並且100%兼容,則可以接受。 – Raynos

1

安全,不是真的 - 因爲你不能確定你延長他們的唯一一個,或者說你實際上延長了正確的方法(見原型 - 上次我檢查,它擴展了內建類,這對其他腳本對內建行爲的期望造成了嚴重破壞)。修改不屬於你自己的對象是一條非常棘手的領土之路(「哦,但這是實際的內置concat(),還是其他一些腳本改變它背後?」)。

參見例如這個更詳細的討論:http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/

相關問題