【问题标题】:How can I emulate "classes" in JavaScript? (with or without a third-party library) [closed]如何在 JavaScript 中模拟“类”? (有或没有第三方库)[关闭]
【发布时间】:2010-09-26 05:33:53
【问题描述】:

如何在 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();

【问题讨论】:

    标签: javascript oop


    【解决方案1】:
    【解决方案2】:

    对于 JavaScript 中的 OOP 的一般理解,您最好阅读Douglas Crockford

    对于道场爱好者(和一般技术)Neil Roberts 有好文章:

    Plain vanilla dojo.declare() 可能是主流库中最先进的 OOP 基础。我有偏见,但不要相信我的话。以下是如何使用它的示例。

    一个普通的对象:

    // 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 的多继承、构造函数的自动链接以及简单易用的超级方法。

    【讨论】:

      【解决方案3】:

      如果您(和您的团队)习惯于 Java,但需要为网站编写一些 JavaScript,也许您应该考虑 Google Web Toolkit (GWT)。它允许您使用转换为 JavaScript 的 Java 编写 JavaScript。不过,我还没有尝试过。

      JavaScript 实际上是一种很酷的语言。它有一些缺陷(包括允许你做非常愚蠢的事情),但只要有一点自律,你就可以做出伟大的事情。 JavaScript 实际上是面向object 的,而不是面向class,但是你可以做很多相同的事情。您没有 (AFAIK) 继承,但它对打字一点也不严格(它强大但也很危险的功能之一),所以您会发现它没有限制。

      【讨论】:

      • 这听起来很有趣。我会进一步调查,谢谢你的链接:)
      【解决方案4】:

      mepcotterell 提供了很好的链接,但我想补充一点,我个人更喜欢将命名空间视为对象,即DoctaJonez.Namespace1 = {};

      【讨论】:

      • 我不知道你能做到这一点,这看起来确实更优雅。感谢您的输入:) +1
      【解决方案5】:

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

      当你在谷歌上搜索“JavaScript 面向对象”时,你会发现一堆例子。通过查看像 Ext JS 这样的流行 JavaScript 框架,您将了解这些概念以及它们在实践中的应用方式。

      【讨论】:

        【解决方案6】:

        使用MooTools。请参阅文章How to write a Mootools Class

        【讨论】:

          【解决方案7】:
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-13
          • 2021-12-18
          • 1970-01-01
          • 1970-01-01
          • 2019-12-14
          • 1970-01-01
          相关资源
          最近更新 更多