2008-12-10 69 views
18

如何在JavaScript中模擬類(和名稱空間)?如何在JavaScript中模擬「類」? (有或沒有第三方庫)

我需要創建一個JavaScript庫並且對該語言的使用經驗有限。我一直認爲它具有對類的本地支持,但它與Java的關係不如我想象的那麼重要。似乎JavaScript中的所有內容實際上都是一個函數。

到目前爲止,我發現的內容對於它是一種動態的弱類型語言有很大的意義,但是這對於習慣於使用強類型語言並使用編譯器的人來說有一點偏離發現我們的錯誤:)

我主要工作在C#和Java,並希望有類似的語法,所以圖書館看起來很熟悉我們的其他C#開發人員,將不得不維護它。

我有以下幾種可行的代碼,但我想知道其他開發者會採取什麼措施。有什麼選擇?有沒有更好的方法?有沒有更可讀的方法?

我知道我想要的東西類似於C#或Java,但我應該接受這一事實,即是JavaScript,但我的目標是嘗試通過使其更加熟悉來緩解其他開發人員的學習曲線併爲他們直觀。

//Perform the namespace setup (this will actually be done with checking 
//in real life so we don't overwrite definitions, but this is kept short 
//for the code sample). 
var DoctaJonez = new function(); 
DoctaJonez.Namespace1 = new function(); 

/** 
* Class description. 
*/ 
DoctaJonez.Namespace1.SomeClass = function() 
{ 
    /** 
    * Public functions listed at the top to act like a "header". 
    */ 
    this.publicFunction = privateFunction; 

    /** 
    * Private variables next. 
    */ 
    var privateVariable; 

    /** 
    * Finally private functions. 
    */ 
    function privateFunction() 
    { 

    } 
} 

//Create an instance of the class 
var myClass = new DoctaJonez.SomeClass(); 

//Do some stuff with the instance 
myClass.publicFunction(); 

回答

1

例如,在http://mckoss.com/jscript/object.htm

當您在「JavaScript面向對象」中搜索時,您會發現一堆示例。通過查看流行的JavaScript框架(如Ext JS),您會體會到這些概念以及它們在實踐中的應用方式。

1

mepcotterell提​​供了很好的鏈接,但我想補充一點,我個人更喜歡將命名空間視爲對象,即DoctaJonez.Namespace1 = {};

+0

我不知道你能做到這一點,看起來更優雅。感謝您的輸入:) +1 – 2008-12-10 14:10:29

9

對於OOP的一般理解在JavaScript不是閱讀Douglas Crockford你不能做的更好:

對於道場的球迷(和一般技術)Neil Roberts有好文章:

平原香草dojo.declare()可能是在圍繞主流庫中最先進的面向對象的基礎。我有偏見,但不要聽我的話。這裏有一些關於如何使用它的例子。

一個普通的對象:

// Let's define a super simple class (doesn't inherit anything). 
dojo.declare("Person", null, { 
    // Class-level property 
    answer: 42, 

    // Class-level object property 
    name: {first: "Ford", last: "Prefect"}, 

    // The constructor, duh! 
    constructor: function(age){ 
    this.age = age; // instance-level property 
    }, 

    // A method 
    saySomething: function(verb){ 
    console.log("I " + verb + " " + 
     this.name.first + " " + this.name.last + "!" + 
     " -- " + this.answer); 
    }, 

    // Another method 
    passportControl: function(){ 
    console.log("I am " + this.age); 
    } 
}); 

使用示例:

// A fan of Ford Perfect 
var fan = new Person(18); 
fan.saySomething("love"); // I love Ford Perfect! -- 42 
fan.passportControl(); // I am 18 

單繼承很容易:

// Let's create a derived class inheriting Person 
dojo.declare("SuperAgent", Person, { 
    // Redefine class-level property 
    answer: "shaken, not stirred", 

    // Redefine class-level object property 
    name: {first: "James", last: "Bond"}, 

    // The constructor 
    constructor: function(age, drink){ 
    // We don't need to call the super class because 
    // it would be done automatically for us passing 
    // all arguments to it. 

    // At this point "age" is already assigned. 

    this.drink = drink; // Instance-level property 
    }, 

    // Let's redefine the method 
    saySomething: function(verb){ 
    // Let's call the super class first 
    this.inherited(arguments); 
    // Pay attention: no need for extra parameters, or any extra code, 
    // we don't even name the class we call --- it is all automatic. 
    // We can call it any time in the body of redefined method 

    console.log("Yeah, baby!"); 
    }, 

    shoot: function(){ console.log("BAM!!!"); } 
}); 

使用示例:

// Let's create a James Bond-wannabe 
var jb007 = new SuperAgent(45, "Martini"); 
jb007.saySomething("dig"); // I dig James Bond! -- shaken, not stirred 
          // Yeah, baby! 
jb007.passportControl(); // I am 45 
jb007.shoot();    // BAM!!! 

// Constructors were called in this order: Person, SuperAgent 
// saySomething() came from SuperAgent, which called Person 
// passportControl() came from Person 
// shoot() came from SuperAgent. 

混入:

// Let's define one more super simple class 
dojo.define("SharpShooter", null, { 
    // For simplicity no constructor 

    // One method to clash with SuperAgent 
    shoot: function(){ 
    console.log("It's jammed! Shoot!"); 
    } 
}); 
基於mixin的

多重繼承:

// Multiple inheritance 
dojo.declare("FakeAgent", ["SuperAgent", "SharpShooter"], { 
    // Let's do it with no constructor 

    // Redefine the method 
    saySomething: function(verb){ 
    // We don't call super here --- a complete redefinition 

    console.log("What is " + verb "? I want my " + this.drink + "!"); 
    }, 
}); 

使用示例:

// A fake agent coming up 
var ap = new FakeAgent(40, "Kool-Aid"); 
ap.saySomething("hate"); // What is hate? I want my Kool-Aid! 
ap.passportControl(); // I am 40 
ap.shoot();    // It's jammed! Shoot! 

// Constructors were called in this order: Person, SuperAgent 
// saySomething() came from FakeAgent 
// passportControl() came from Person 
// shoot() came from SharpShooter. 

正如你所看到的,dojo.declare()給所有必需品用一個簡單的使用API:直接單一繼承,基於mixin的多繼承,構造函數的自動鏈接以及無障礙超級方法。

1

如果您(和您的團隊)習慣於Java,但需要爲網站製作一些JavaScript,或許您應該考慮Google Web Toolkit(GWT)。它可以讓你使用Java編寫JavaScript代碼,並將其轉換爲JavaScript。雖然我沒有嘗試過。

JavaScript實際上是一種很酷的語言。它有一些缺陷(包括允許你做很愚蠢的東西),但有一點自我學習,你可以做出偉大的東西。 JavaScript實際上是對象爲導向,而不是爲導向,但你可以做很多相同的東西。你沒有(AFAIK)繼承,但它並不嚴格(它的強大但危險的功能之一),所以你會發現它不是限制。

+0

這聽起來很有趣。我會進一步調查,謝謝你的鏈接:) – 2008-12-11 09:12:13

相關問題