2008-12-10 64 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

相关问题