Sunday, December 8, 2013

Object-Oriented Programming in JavaScript

Access Modifiers

It is a convention in JavaScript that a class member whose name starting with an underscore is "private", that is, it is intended for internal use and should not be considered part of the public API of the class. However, one can in fact define a de facto private members using closures. In the following example, new MyClass will return an object with only the properties assigned to this object and in the prototype object of the class.
var MyClass = (function () {
    // private static field
    var counter = 0;

    // constructor
    var ctor = function (_name) {
        // private instance field
        var _id = ++counter;
        // public instance method
        // Private instance members can only be accessed this way
        this.getName = function () { return _name }; // readonly
        this.getID = function () { return _id }; // readonly
    };
    // public instance method (shared across instances)
    // Note that class methods cannot access instance members.
    ctor.prototype.toString = function () {
        return 'Hi! My my name is ' + this.getName()
        + ', my id is ' + this.getID()
        + ' and there are ' + counter + ' instances in total.'
    };
    // public static method
    ctor.getNumInstances = function () { return counter };
    return ctor;
})();
// Error: cannot access id outside ctor
MyClass.prototype.setID = function(id){ this.id = id; }

Inheritance

Javascript doesn't exactly have subclass objects, but prototype is a useful workaround to make a "base class" object of certain functions that act as objects. For example:
/* Definition of class Person */
var Person = function(name) {
    this.name = name;    
    this.canTalk = true;
    this.greet = function() {
        if (this.canTalk) console.log("Hi, I'm " + this.name);        
    };
};
/* Definition of subclass Employee */
var Employee = (function() {
    var ctor = function(name, title) {
        // call parent constructor
        Person.call(this, name);
        // initializations for Emplyee        
        this.title = title;
    };
    // store the method before overriding it
    var _greet = ctor.greet || Person.prototype.greet;

    // overriding parent's method
    ctor.prototype.greet = function() {
        // call the original method
        _greet.apply(this, arguments); 
        console.log("I'm a " + this.title);        
    };
    // setup the prototype chain
    ctor.prototype = Object.create(Person.prototype);
    ctor.prototype.constructor = ctor; // repair the inherited constructor
    return ctor;
})();

References and Resources

1. Introduction to Object-Oriented JavaScript
2. Prototypes Are Not Classes
3. Constructors in JavaScript objects
4. Douglas Crockford: Advanced JavaScript (Video)
5. Constructors Considered Mildly Confusing
JavaScript The Definitive Guide, 6th Edition,  Chapter 9
(http://js-bits.blogspot.com.au/2010/08/javascript-inheritance-done-right.html)

Friday, December 6, 2013

CoffeeScript and LiveScript

I am familiar with JavaScript, and I am interested in CoffeeScript and LiveScript. I really need some good tutorials before I get enough brevity to use them in my projects.

Functional Programming in JavaScript using LiveScript and prelude.ls