views:

833

answers:

7

Update: I've wikified this so it can become a more useful resource.

What is the best way to emulate classes (and namespaces) in Javascript?

I need to create a Javascript library and have limited experience with the language. I always thought that it had native support for classes, but it is less related to Java than I had assumed. It seems that everything in javascript is actually a function.

What I have found out so far makes a lot of sense with it being a dynamic weakly typed language, but this makes it a bit of a departure for people who are used to having a strongly typed language and using a compiler to spot our errors :)

I mainly work in C# and Java, and was hoping for something syntacticaly similar so the library would look familiar for our other C# developers that will have to maintain it.

I have the following sort of code which works, but was wondering what other developer's takes would be on this. What are the alternatives? Is there a way that is better? Is there a way that is more readable?

I understand that what I want is something similar to C# or Java when I should just accept the fact that this is Javascript, but my aim is to try to ease the learning curve for other developers by making it more familiar and intuitive for them.

//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  A: 

eg. http://mckoss.com/jscript/object.htm

you'll find a bunch of examples when googling for "javascript object-oriented". by taking a look at popular js-frameworks like ExtJS you'll get a feeling for these concepts and how they're applied in practice.

Andre Steingress
+1  A: 

mepcotterell provides good links, but I'd like to add that I personally prefer to see namespaces as objects i.e. DoctaJonez.Namespace1 = {};.

annakata
I didn't know you could do that, that does look a lot more elegant. Thanks for the input :) +1
DoctaJonez
+5  A: 

For general understanding of OOP in JavaScript you can't do better than read Douglas Crockford:

For Dojo fans (and for general techniques) Neil Roberts has good articles:

Plain vanilla dojo.declare() probably the most advanced OOP foundation in mainstream libraries around. I am biased but don't take my word for it. Here are examples on how to use it:

// 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!");
  },

  // new method
  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!");
  }
});

// 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 SuperAgent(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

As you can see dojo.declare() gives all necessities with a simple to use API: straight single inheritance, mixin-based multiple inheritance, automatic chaining of constructors, and no-hassle super methods.

Eugene Lazutkin
A: 

Mozilla MDC : Prototype based languages

https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages

+1  A: 

Using mootools:

http://www.mootorial.com/wiki/mootorial/09-howtowriteamootoolsclass

Khnle
+1  A: 

If you (and your team) is used to Java but need to make some JavaScript for a web site, perhaps you should consider GWT. It lets you code JavaScript using Java, wich is converted to JavaScript. I haven't tried it, though.

JavaScript is actually a quite cool language, it has a few flaws (including allowing you to do very stupid stuff), but with a little self dicipline you can make great stuff. JavaScript is actually Object oriented, not so much class oriented, but you can do much of the same stuff. You don't have (AFAIK) inheritance, but it's not strict at all (one of it's powerful but allso dangerous features) with typing so you'll find it's not limiting.

Stein G. Strindhaug
This sounds very interesting. I will investigate this further, thank you for the link :)
DoctaJonez