2008-10-22 66 views
9

我一直在試圖學習如何添加測試到現有的代碼 - 目前閱讀閱讀Working Effectively With Legacy Code。我一直在嘗試應用JavaScript中的一些原則,現在我試圖提取一個接口。有沒有一種「正確」的方式來在JavaScript中進行繼承?如果是這樣,那是什麼?

在尋找在JavaScript中創建接口,我找不到很多 - 我發現有關繼承,似乎他們有幾種不同的方式。 (有些人創建了自己的基類來提供有用的方法來使繼承更容易,一些使用函數,一些使用原型)。

什麼是正確的方法?有一個在JavaScript中提取接口的簡單示例?

回答

13

有沒有權利正確的方式,因爲這麼多人做這麼多不同的事情..有許多有用的模式。

Crockford暗示你「隨穀物走」,或者以對應於javascript原型性質的方式寫javascript。

當然,他繼續表明,Netscape建議的原始模型實際上已經被破壞。他將其標記爲「僞古典」,並指出了遵循該模型所涉及的許多錯誤方向和不必要的複雜性。

他寫了「對象」函數作爲補救措施(現在稱爲Object.create())。它允許一些非常強大的原型模式。

當你不得不使用遺留的javascript時,開發乾淨的界面並不總是很容易,特別是當你處理大型系統時,通常包括多個庫,並且每個實現獨特的樣式和不同的繼承模式。一般來說,我認爲繼承的「正確方法」是允許您編寫一個乾淨的界面,該界面在遺留代碼的上下文中表現良好,但也允許您重構並消除一段時間內的舊依賴關係。

考慮到主要庫模式之間的差異,我發現在我自己的工作中最成功的路線是讓我的接口完全獨立於庫接口。如果有用的話,我會使用一個庫或模塊,但不會被綁定到它。這使我可以重構很多代碼,逐步淘汰一些庫,並將庫用作腳手架,這些腳手架可以稍後進行優化。

沿着這些路線,我寫了靈感來自Crockford寄生繼承模式的接口。這簡直就是一場勝利。在硬幣的另一面,我相信你可能會挑選一個圖書館,在你的團隊中執行它,並遵守它的繼承模式和它的接口約定。

+2

怎麼樣的聯繫? – pc1oad1etter 2009-09-17 13:20:08

3

還可以查看Dean Edwards的Base.js。你可以看看它here,博客文章是不言自明的。

5

您正在看兩件不同的事情。

首先你有接口。實現這一點的最可接受的方式是通過鴨子打字(「如果它看起來像一隻鴨子,鴨子像鴨子那麼它是一隻鴨子」)。這意味着如果一個對象實現了接口的一組方法,那麼它就是那個接口。您可以通過定義一個接口的方法名稱來實現這一點。然後檢查一個對象是否實現了這個干涉,如果它實現了這些方法。這裏是我掀起的代碼示例:

function Implements(obj, inter) 
{ 
    var len = inter.length, i = 0; 
    for (; i < len; ++i) 
    { 
     if (!obj[inter[i]]) 
      return false; 
    } 
    return true; 
} 

var IUser = ["LoadUser", "SaveUser"]; 

var user = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     }, 

     SaveUser : function() 
     { 
      alert("Save"); 
     } 
    }; 

var notUser = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     } 
    }; 

alert(Implements(user, IUser)); 
alert(Implements(notUser, IUser)); 

現在你有繼承。 JS沒有內置的繼承;所以你必須手動實現它。這只是將一個對象的屬性「複製」到另一個對象的問題。下面是另一個代碼示例(並非十全十美,但它說明了這一點):

function InheritObject(base, obj) 
{ 
    for (name in base) 
    { 
     if (!obj[name]) 
      obj[name] = base[name]; 
    } 
} 

var Base = { 
     BaseFunc : function() { alert("BaseFunc from base"); }, 
     InheritFunc : function() { alert("InheritFunc from base"); } 
    } 

var Inherit = { 
     InheritFunc : function() { alert("InheritFunc from inherit"); }, 
     AnotherFunc : function() { alert("AnotherFunc from inherit"); } 
    } 

InheritObject(Base, Inherit); 

Inherit.InheritFunc(); 
Inherit.BaseFunc(); 
Inherit.AnotherFunc(); 

Base.BaseFunc(); 
Base.InheritFunc(); 

你可能想看看http://www.mootools.net。它有我最喜歡的類實現。你也一定要看看「專業的Javascript設計模式」

http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X

這本書介紹了有關如何在JavaScript模仿OOP良好的細節。

+0

+1簡單明瞭的解釋! – 2010-03-31 14:44:42

6

JavaScript中沒有類,只有對象。
但如果你堅持模擬類基於面向對象的模型,你可以使用這個:

 
function ChildClass() { 
    ParentClass.call(this); 
    // Write the rest of your constructor function after this point. 
}; 
ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype); 

jQuery.extend是從jQuery庫中的「淺拷貝」功能。您可以用任何其他對象複製/克隆功能來替換它。

+1

第一句話不能再強調 – Claudiu 2010-07-01 16:26:24

0

原型提供自己拿上繼承,從http://www.prototypejs.org/api/class/create

var Animal = Class.create({ 
    initialize: function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    }, 

    speak: function() { 
    alert(this.name + " says: " + this.sound + "!"); 
    } 
}); 

// subclassing Animal 
var Snake = Class.create(Animal, { 
    initialize: function($super, name) { 
    $super(name, 'hissssssssss'); 
    } 
}); 
相關問題