2009-11-04 30 views
1

我從this post瞭解到,這是修改Object的JavaScript原型的反模式。不過,我很好奇,如果它被廣泛認爲是修改其他「內置」原型的反模式。例如:假設我們想爲CanvasRenderingContext2D添加一個setPixel(x,y,color)函數 - 以抽象出獲取上下文圖像數據,設置像素爲特定顏色,並將圖像數據放回的責任。這是修改JavaScript內置原型的反模式嗎?

CanvasRenderingContext2D.prototype.setPixel = function(x, y, color){ 
    var imgdata = this.createImageData(1,1); 
    imgdata.data[0] = color.r; 
    imgdata.data[1] = color.g; 
    imgdata.data[2] = color.b; 
    imgdata.data[3] = color.a; 
    this.putImageData(imgdata,x,y); 
};

我還沒有測試過這段代碼,但你明白了。是否這樣反對'最佳實踐'?

+1

這個評論與你的問題沒有關係,但是如果你想在Safari 3(或者其他)中擴展CanvasRenderingContext2D的原型,你需要這樣訪問它: document.createElement('canvas')。getContext ('2d').__ proto__ – 2009-11-04 20:38:36

+0

@Fabien - 爲什麼Safari需要這樣的籃球,而Safari 4是否需要這樣的? – 2009-11-04 20:40:24

+0

@James Safari 4不需要這個,但是我沒有意識到Safari 3需要這個奇怪的東西。偉大的提示法比安! – JasonWyatt 2009-11-04 20:45:22

回答

3

一般來說,如果您要在JavaScript中爲其中一個基礎對象添加原型,您應該有一個很好的理由,並且確實沒有理由修改Object,因爲您不知道如何預測結束結果將是該修改。

我傾向於將startsWith,trim和其他一些函數添加到String中,例如,因爲這些是輔助函數,就像爲Firefox添加一些函數但不包含IE只是有意義的(例如過濾函數)。

因此,添加到畫布是好的,但是,如果有人正在使用您的庫,並使用excanvas會怎麼樣。會造成問題嗎?

你可能想要探索它,或記錄它不適用於excanvas,如果你有一個小的測試來表明它,請包括它,以便如果以後有新版本,並且你的問題消失的人可以驗證。

UPDATE: 你會想這樣做:

if (!CanvasRenderingContext2D.setPixel) { 
... 
} 

這樣一來,如果有人做了包括一個由名字,你不會覆蓋它,但你必須優雅地處理它。

0

只要功能或命名不會覆蓋已存在的內容,我不會看到任何問題。我知道一些修改了Trim功能的string原型。

http://www.somacon.com/p355.php

有什麼好笑的,C#現在有什麼所謂的擴展方法,有效地做同樣的事情。

4

我不會這樣做,因爲它很難追蹤哪裏實施。它還引入了兩個人壓倒相同行爲的風險。

+1

但是,如果一個瀏覽器在其Canvas版本中具有某些功能,並且希望將其添加到不包含它的另一個瀏覽器,它可以幫助簡化。 – 2009-11-04 20:37:23

+0

我同意,它很難追蹤事物的實現,但它似乎是一個更優雅的解決方案,而不是用自定義對象來包裝對象,只是添加一個或兩個函數。 所以我想一個新的問題會是:這是「優雅」的謬誤?有點像goto語句? – JasonWyatt 2009-11-04 20:39:56

+0

我不認爲它與goto語句的公平比較,但我確實認爲優雅是一種錯覺。它可能會使代碼看起來更好,但對於不熟悉代碼的開發人員而言,我認爲這會使代碼更難理解。 – 2009-11-04 20:46:03

1

絕對不是;如果方法以這種方式與對象相關,那麼它是一個優雅的解決方案。

0

並非如此,但如果Ajax庫製造商無法依賴內置類型及其屬性,可能會遇到問題。所以你可以打破依賴於某些行爲的代碼。

1

所有這些「反模式」的建議不要盲目採用。無論他們說什麼,有時候最好的答案就是咬緊牙關,違背慣例讓事情順利進行。這當然主要取決於你的情況。

我想起了一種情況,在這種情況下,重新組織代碼的時間是「正確的方式」,當一個簡單的GO TO工作得很好而且只需要幾分鐘時間來執行時。最後,創建了一堆錯誤,因爲代碼被改變了,不需要改變。我是GO TO陳述的粉絲嗎?一定不行!但是,如果使用防止一個月的頭痛,那麼毫無疑問。