Thursday, February 9, 2017

Creating Class Objects in JavaScript

Object Factory Pattern


  • A function that creates and returns a new object (o in code below) after it sets data and function members.
  • Members can be data values (e.g. radius) or functions (e.g. area(), circumference(), print()).
  • Members have access to other members using the this keyword (e.g. area() function accesses this.radius).
Source:

var CircleFactory = function(radius){
    var o = {};
    o.radius = radius;
    o.area = function(){
        return 22/7 * this.radius * this.radius;
    }
    o.circumference = function(){
        return 2 * 22/7 * this.radius;
    }
    o.print = function(){
        console.log("radius: " + this.radius + 
        " area: " + this.area() 
        + " circumference: " + this.circumference());
    }
    return o;
}

// Usage
var circle1 = CircleFactory(10);
circle1.print();
var circle2 = CircleFactory(15);
circle2.print();

Output:

radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428

Constructor Function Pattern

  • A normal function is defined. This can serve as the Constructor function (i.e. Circle). 
  • Members are defined using the this keyword. These members are publicly available. One member can access another member using the this keyword (e.g. area() function accesses this.radius).
  • Members can be data values (e.g. radius) or functions (e.g. area(), circumference(), print()).
  • An instance of a function (aka function object) is created using the new keyword.
  • Members are invoked on the function object (not on the Constructor function).
Source:
var Circle = function(radius) {
    this.radius = radius;

    this.area = function() {
        return 22 / 7 * this.radius * this.radius;
    }
    this.circumference = function() {
        return 2 * 22 / 7 * this.radius;
    }

    this.print = function() {
        console.log("radius: " + this.radius 
        + " area: " + this.area() 
        + " circumference: " + this.circumference());
    }
}

// Usage
var circle1 = new Circle(10);
circle1.print();
var circle2 = new Circle(15);
circle2.print();

Output:
radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428

Constructor Function using Prototype Pattern

  • First, see description of Constructor Function Pattern above. Constructor Function using Prototype Pattern is just a more efficient implementation of the Constructor Function Pattern.
  • Every new object constructed has it's own copy of radius, area(), circumference(), print() functions. The radius is going to vary from one function object to another so it makes sense that every new function object maintain it's own copy of radius. But the implementation of area(), circumference(), print() functions does not differ from one function object to another! When a large number of function objects are created, this duplication of member function code adds unnecessary memory overhead.
  • The prototype property on the function allows us to set a member of the function once and have it available for all new function objects.
  • Both data (PI) and functions (area(), circumference(), print()) can be defined on the prototype of a function object.
Source:
var Circle = function(radius) {
    this.radius = radius;
}

Circle.prototype.PI = 22/7;

Circle.prototype.area = function() {
    return this.PI * this.radius * this.radius;
}
Circle.prototype.circumference = function() {
    return 2 * this.PI * this.radius;
}
Circle.prototype.print = function() {
    console.log("radius: " + this.radius 
    + " area: " + this.area() 
    + " circumference: " + this.circumference());
}

// Usage
var circle1 = new Circle(10);
circle1.print();
var circle2 = new Circle(15);
circle2.print();

Output:
radius: 10 area: 314.2857142857143 circumference: 62.857142857142854
radius: 15 area: 707.1428571428571 circumference: 94.28571428571428