Как я могу эмулировать "классы" в JavaScript? (с или без сторонней библиотеки)

Как я могу эмулировать классы (и пространства имен) в JavaScript?

Мне нужно создать библиотеку JavaScript и иметь ограниченный опыт работы с языком. Я всегда думал, что у него есть родная поддержка классов, но он менее связан с Java, чем я предполагал. Кажется, что все в JavaScript на самом деле является функцией.

То, что я обнаружил до сих пор, имеет большой смысл, поскольку он является динамически слабо типизированным языком, но это делает его немного отходом для людей, которые привыкли иметь строго типизированный язык и использовать компилятор для определения наши ошибки:)

Я в основном работаю на С# и Java и надеялся на что-то синтаксически похожее, чтобы библиотека выглядела знакомой для наших других разработчиков С#, которые должны будут ее поддерживать.

У меня есть следующий вид кода, который работает, но мне было интересно, что будет делать другой разработчик. Каковы альтернативы? Есть ли способ, который лучше? Есть ли способ, который более читабельен?

Я понимаю, что то, что я хочу, похоже на С# или 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();

Ответы

Ответ 2

Для общего понимания ООП в JavaScript вы не можете сделать лучше, чем читать Дуглас Крокфорд:

Для поклонников Dojo (и для общих методов) Нил Робертс имеет хорошие статьи:

Обычная ваниль dojo.declare(), вероятно, является самой передовой базой ООП в основных библиотеках. Я предвзятый, но не верю мне на слово. Вот примеры того, как его использовать.

Обычный ванильный объект:

// Let 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 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 redefine the method
  saySomething: function(verb){
    // Let 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 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 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 jammed! Shoot!");
  }
});

Множественное наследование на основе Mixin:

// Multiple inheritance
dojo.declare("FakeAgent", ["SuperAgent", "SharpShooter"], {
  // Let 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 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

Например, в http://mckoss.com/jscript/object.htm.

Вы найдете множество примеров, когда googling для "JavaScript-объектно-ориентированного". Взглянув на популярные JavaScript-фреймворки, такие как Ext JS, вы получите представление об этих концепциях и о том, как они применяются на практике.

Ответ 4

mepcotterell предоставляет хорошие ссылки, но я хотел бы добавить, что лично я предпочитаю видеть пространства имен как объекты, т.е. DoctaJonez.Namespace1 = {};.

Ответ 6

Если вы (и ваша команда) используется на Java, но вам нужно сделать какой-то JavaScript для веб-сайта, возможно, вам стоит подумать о Google Web Toolkit (GWT). Он позволяет вам кодировать JavaScript с использованием Java, который преобразуется в JavaScript. Однако я не пробовал.

JavaScript на самом деле довольно классный язык. У него есть несколько недостатков (в том числе позволяет вам делать очень глупые вещи), но с небольшим самодисциплином вы можете сделать отличный материал. JavaScript на самом деле объектно-ориентированный, не столько ориентированный на класс, но и вы можете делать многое из того же материала. У вас нет наследства (AFAIK), но он не является строгим (одна из его мощных, но и опасных функций) с набрав, поэтому вы не найдете этого ограничения.