Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

After searching and reading about how to writing Object Oriented JavaScript, I summarized them in the below code:

/********************************************************/
// Enumeration.
var Fruits = {
    Apple: 0,
    Orange: 1,
    Watermelon: 2,
    Banana: 3
}; // <-- Don't forget ;

// Using enumeration.
// function SquishFruit(fruit) {
//     switch (fruit) {
//         case Fruits.Apple : Chop();
//         case Fruits.Orange : Pulp();
//         case Fruits.Watermelon : Smash();
//         case Fruits.Banana : Peel();
//     }
/********************************************************/

/********************************************************/
// Base class.
function BaseClass(arg) {

    // Constructor.
    alert("I am BaseClass constructor.\n arg=" + arg);

    // Private fields.
    // Use m_privateField, Not this.m_privateField in the class scope.
    var m_privateField = "I am BaseClass.m_privateField";

    // Public fileds.
    // Use this.PublicField, Not PublicField in the class scope.
    this.PublicField = "I am BaseClass.PublicField";

    // Private methods.
    // Invoke PrivateMethod(), Not this.PrivateMethod() in the class scope.
    function PrivateMethod(arg) {
        alert("I am BaseClass.PrivateMethod.\n arg=" + arg + "\n m_privateField=" + m_privateField);
        return;
    }

    // Public methods.
    // ----------------------------------------------------------------------
    // Note: Using "prototype" increases efficiency but breaks the encapsulation.
    // Example:
    // function MyClass() {
    //     var _value = 1;
    // }
    // MyClass.prototype.getValue = function () {
    //     // the function assigned to getValue is
    //     // no longer in scope with _value it can't access it.
    //     return _value;
    // }
    // ----------------------------------------------------------------------
    // Invoke this.PublicMethod(), Not PublicMethod() in the class scope.
    this.PublicMethod = function (arg) {
        alert("I am BaseClass.PublicMethod.\n arg=" + arg + "\n PublicField=" + this.PublicField);
        return;
    };  // <-- Don't forget ;

    // Virtual methods.
    // Invoke this.VirtualMethod(), Not VirtualMethod() in the class scope.
    this.VirtualMethod = function (arg) {
        alert("I am BaseClass.VirtualMethod.\n arg=" + arg + "\n");
        return;
    };  // <-- Don't forget ;
}

// Static fields.
BaseClass.StaticField = "I am BaseClass.StaticField";

// Static methods.
BaseClass.StaticMethod = function (arg) {
    alert("I am BaseClass.StaticMethod.\n arg=" + arg + "\n StaticField=" + BaseClass.StaticField);
    return;
}
/********************************************************/

/********************************************************/
// Derived class.
function DerivedClass(arg) {

    // Call base class constructor.
    // Never forget this call.
    BaseClass.call(this, arg);

    // Constructor.
    alert("I am DerivedClass constructor.\n arg=" + arg);

    // Private fields.
    // Use m_privateField2, Not this.m_privateField2 in the class scope.
    var m_privateField2 = "I am DerivedClass.m_privateField2";

    // Public fileds.
    // Use this.PublicField2, Not PublicField2 in the class scope.
    this.PublicField2 = "I am DerivedClass.PublicField2";

    // Private methods.
    // Invoke PrivateMethod2(), Not this.PrivateMethod2() in the class scope.
    function PrivateMethod2(arg) {
        alert("I am DerivedClass.PrivateMethod.\n arg=" + arg + "\n m_privateField2=" + m_privateField2);
        return;
    }

    // Public methods.
    // Invoke this.PublicMethod2(), Not PublicMethod2() in the class scope.
    this.PublicMethod2 = function (arg) {
        alert("I am DerivedClass.PublicMethod2.\n arg=" + arg + "\n PublicField2=" + this.PublicField2);
        return;
    };  // <-- Don't forget ;

    // Virtual methods.
    // Invoke this.VirtualMethod(), Not VirtualMethod() in the class scope.
    this.VirtualMethod = function (arg) {
        alert("I am DerivedClass.VirtualMethod.\n arg=" + arg + "\n");
        return;
    };  // <-- Don't forget ;
}

// Make DerivedClass derived from BaseClass.
// Never forget these two lines.
// Note: Constructor of BaseClass invoked here.
DerivedClass.prototype = new BaseClass; // () not required!
DerivedClass.prototype.constructor = DerivedClass;

// Static fields.
DerivedClass.StaticField2 = "I am DerivedClass.StaticField2";

// Static methods.
DerivedClass.StaticMethod2 = function (arg) {
    alert("I am DerivedClass.StaticMethod2.\n arg=" + arg + "\n StaticField2=" + DerivedClass.StaticField2);
    return;
}
/********************************************************/

/********************************************************/
// Tests.

alert("---------- Tests started ----------");

// Test enumuration.
var fruit = Fruits.Apple;
alert("Test enumuration.\n fruit=" + fruit);

// Test BaseClass.
var baseClass = new BaseClass("Hello BaseClass.");

// Test private fields.
alert("Test private fields:\n baseClass.m_privateField=" + baseClass.m_privateField); // undefined.

// Test public fields.
alert("Test public fields:\n baseClass.PublicField=" + baseClass.PublicField);

// Test private methods.
// TypeError: baseClass.PrivateMethod is not a function
// baseClass.PrivateMethod("Hello PrivateMethod.");

// Test public methods.
baseClass.PublicMethod("Hello PublicMethod.");

// Test virtual methods.
baseClass.VirtualMethod("Hello VirtualMethod.");

// Test Static fields.
// Note: Use class name instead of objact name.
// BaseClass.StaticField expression is correct.
// baseClass.StaticField expression is incorrect (baseClass.StaticField value is undefined).
alert("Test Static fields:\n BaseClass.StaticField=" + BaseClass.StaticField);

// Test Static methods.
// Note: Use class name instead of objact name.
BaseClass.StaticMethod("Hello StaticMethod.");

// Test DerivedClass.
var derivedClass = new DerivedClass("Hello DerivedClass.");

// Test private fields.
alert("Test private fields:\n derivedClass.m_privateField=" + derivedClass.m_privateField); // undefined.
alert("Test private fields:\n derivedClass.m_privateField2=" + derivedClass.m_privateField2); // undefined.

// Test public fields.
alert("Test public fields:\n derivedClass.PublicField=" + derivedClass.PublicField);
alert("Test public fields:\n derivedClass.PublicField2=" + derivedClass.PublicField2);

// Test private methods.
// TypeError: derivedClass.PrivateMethod is not a function
// derivedClass.PrivateMethod("Hello PrivateMethod.");
// TypeError: derivedClass.PrivateMethod2 is not a function
// derivedClass.PrivateMethod2("Hello PrivateMethod2.");

// Test public methods.
derivedClass.PublicMethod("Hello PublicMethod.");
derivedClass.PublicMethod2("Hello PublicMethod2.");

// Test virtual methods.
derivedClass.VirtualMethod("Hello VirtualMethod.");

// Test Static fields.
// Note: Use class name instead of objact name.
alert("Test Static fields:\n DerivedClass.StaticField=" + DerivedClass.StaticField); // undefined. Use BaseClass.StaticField.
alert("Test Static fields:\n DerivedClass.StaticField2=" + DerivedClass.StaticField2);

// Test Static methods.
// Note: Use class name instead of objact name.
// TypeError: DerivedClass.StaticMethod is not a function
// DerivedClass.StaticMethod("Hello StaticMethod.");
DerivedClass.StaticMethod2("Hello StaticMethod2.");

/********************************************************/

/********************************************************/
// References:
// http://people.apache.org/~martinc/OOP_with_ECMAScript/
// http://stackoverflow.com/questions/107464/is-javascript-object-oriented
// https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
// https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model
/********************************************************/

I test this code and it works fine.

I test it by IE9, FireFox 15 and Google Chrome 22.

Some of features that I could not implement are:

  • Namespaces in human readable form.
  • Private static fields.
  • Private static methods.

Do I miss any thing about Object Oriented Programming in JavaScript or are there any better idea for Encapsulation, Polymorphism and Inheritance classes?

share|improve this question

closed as not constructive by asawyer, Vikdor, zzzzBov, Beska, lanzz Oct 2 '12 at 17:33

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

1  
you should have a root object from which you then expand your code as recommended in the book good parts.. –  Anirudha Oct 2 '12 at 17:29
    
The semicolon after the closing brace of an object initializer is not actually required as implied by your comment. –  lanzz Oct 2 '12 at 17:34
add comment

1 Answer

This is a good structure in JavaScript I use that has good encapsulation and abstraction.

    var musicPlayer = {
               init: function(target_items, name){
                  //do something
                  anotherFunction('test');
                },
                anotherFunction(argument){
                }
    };
    $(document).ready(function(){
         musicPlayer.init('.container', 'tooltip');

    });
share|improve this answer
    
There is only one line of jQuery above and it has no impact on the question or answer. –  jahroy Oct 2 '12 at 17:39
    
I just usually use it with requireJS and then call it when the DOM has loaded –  josh Oct 2 '12 at 18:24
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.