如何在 JavaScript 中模拟“类”? (有或没有第三方库)[关闭]

Posted

技术标签:

【中文标题】如何在 JavaScript 中模拟“类”? (有或没有第三方库)[关闭]【英文标题】:How can I emulate "classes" in JavaScript? (with or without a third-party library) [closed] 【发布时间】: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();

【问题讨论】:

【参考方案1】: 3 ways to define a JavaScript class Object-oriented JavaScript JavaScript Tutorial: Functions and Classes

【讨论】:

【参考方案2】:

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

Classical Inheritance in JavaScript Prototypal Inheritance in JavaScript Private Members in JavaScript

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

Color by numbers: dojo.delegate JavaScript Metaclass Programming

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 *** 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】:

参见Mozilla Developer Network (MDC) 文章Class-Based vs. Prototype-Based Languages

【讨论】:

以上是关于如何在 JavaScript 中模拟“类”? (有或没有第三方库)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Javascript 中模拟 SQL Coalesce 语句的功能

CSS伪类选择器active模拟JavaScript点击事件

JavaScript是如何工作的:深入类和继承内部原理 + Babel和TypeScript之间转换

javascript“类”与继承总结和回顾-韩烨

使用phonegap在android模拟器中调试javascript

如何在 JavaScript 单元测试中模拟 localStorage?