All the OOP

ES5 Edition

ES5 vs. ES6

 If you remember anything about the differences between ES5 & ES6 OOP be it this:

  • In ES6 we use the keyword ​class to define our classes, in ES5 we use the function keyword.
  • In ES6 we have a constructor method for the construction of each instance of our objects, in ES5 any code we have in our main function block is used.
  • In ES6 we have getters/setters, in ES5 we use the this context of the object(function). 
  • In ES6 we have "true" inheritance. In ES5 we have prototypal inheritance.

ES5 vs. ES6

Defining a class and it's constructor

//this is just a function
function PurchaseOrder(){

    // However, it will have special behavior when
    // INVOKED with the new keyword in that it 
    // RETURNS itself as a unique object reference.

    //this is 'constructor' code
    this.name = 'Bulk Cheetos'; 
}

// proper usage
var order = new PurchaseOrder(); 
console.log(order.name) // 'Bulk Cheetos'

// this is "allowed"
var order = PurchaseOrder(); //undefined
console.log(order.name); // Error

ES5

ES6

// It doesn't "look" like a function
class PurchaseOrder{ 

    //explicit constructor logic called
    //when instantiated with new
    constructor(){
        this.name = 'Bulk Cheetos'
    }
}

var order = new PurchaseOrder();

console.log(order.name); // 'Bulk Cheetos'

//this is NOT allowed
var order = PurchaseOrder();
//TypeError: Classes can’t be function-called

*Class definitions are not hoisted

ES5 vs. ES6

Defining properties of a class

//this is just a function
function PurchaseOrder(){

    //this is 'constructor' code
    var name = 'Bulk Cheetos'; 

    this.name = function(){
        return name;
    }
}

// proper usage
var order = new PurchaseOrder(); 
order.name(); // 'Bulk Cheetos'

ES5

ES6

// It doesn't "look" like a function
class PurchaseOrder{ 

    constructor(){
        this.name = 'Bulk Cheetos'
    }

    get name(){
        return this.name;
    }

    set name(val){
        this.name = val;
    }
}

var order = new PurchaseOrder();
order.name; // 'Bulk Cheetos'

ES5 vs. ES6

Defining methods of a class

//this is just a function
function PurchaseOrder(){

    //this is 'constructor' code
    var name = 'Bulk Cheetos'; 

    this.print = function(){
        console.log('Printing....');
    };
}

// proper usage
var order = new PurchaseOrder(); 
order.print(); // 'Printing...'

ES5

ES6

// It doesn't "look" like a function
class PurchaseOrder{ 

    constructor(){
        this.name = 'Bulk Cheetos'
    }

    print(){
        console.log('Printing...');
    }
}

var order = new PurchaseOrder();
order.print(); // 'Printing...'

ES5 vs. ES6

Inheritance

//this is just a function
function Order(){
    this.id = 'HH244';  
}

Order.prototype.print = function(){
    console.log('Printing....');
};

function PurchaseOrder(){
    Order.call(this);

    this.name = 'Bulk Cheetos'; 
}

PurchaseOrder.prototype = 
Object.create(Order.prototype, {
    constructor: {
        value: PurchaseOrder
    }
});

ES5

ES6

// It doesn't "look" like a function
class Order{ 
    constructor(){
        this.id = 'AA2245';
    }

    print(){
        console.log('Printing...');
    }
}

class PurchaseOrder extends Order{ 

    constructor(){
        this.name = 'Bulk Cheetos'
    }
}

ES5

Overriding a super constructor

(don't use super constructor)

Constructor Overloading

//this is just a function
function Order(){
    this.id = 'HH244';  
}

Order.prototype.print = function(){
    console.log('Printing....');
};

function PurchaseOrder(){
    //Order.call(this); //Don't invoke the super constructor

    this.name = 'Bulk Cheetos'; 
}

PurchaseOrder.prototype = 
Object.create(Order.prototype, {
    constructor: {
        value: PurchaseOrder
    }
});

//PurchaseOrder will still have the print method but no 'id' property
//PurchaseOrder will have any methods defined on the prototype
//this is just a function
function Order(){
    this.id = 'HH244';  
}

Order.prototype.print = function(){
    console.log('Not implemented');
}

function PurchaseOrder(){
    Order.call(this);

    this.name = 'Bulk Cheetos'; 
}

PurchaseOrder.prototype = 
Object.create(Order.prototype, {
    constructor: {
        value: PurchaseOrder
    }
});

PurchaseOrder.prototype.print = function(){
    console.log('Printing to laser printer');
}

ES5

Overriding a super method

(Don't use that one, use this one)

Method Overriding

function Order(){
    this.id = 'HH244';  
}

Order.prototype.print = function(){
    console.log('Checking paper...');
}

function PurchaseOrder(){
    Order.call(this);

    this.name = 'Bulk Cheetos'; 
}

PurchaseOrder.prototype = 
Object.create(Order.prototype, {
    constructor: {
        value: PurchaseOrder
    }
});

PurchaseOrder.prototype.print = function(){
    Order.prototype.print.call(this);
    console.log('Printing to laser printer');
}

var order = new PurchaseOrder();
order.print();
//'Checking paper...'
//'Printing to laser printer'

ES5

Extending a super method

Method Extension

function Order(){
    var id = 'BB3445';
    
    Object.defineProperty(this, "id", {
        get: function(){
            return id;
        },
        set: function(val){
            id = val;
        },
        enumerable: true, //does this show up when inspecting properties 
        configurable: false, // don't allow this property to be removed from object instances
        writable: true //allow this property to be modified, default is false when using defineProperty
    });  
}

function PurchaseOrder(){} //Define our class

//Inherit from Order by setting prototype and constructor
PurchaseOrder.prototype = new Object(Order.prototype, {
    constructor: {
        value: PurchaseOrder,
        configurable: true,
        enumerable: true,
        writable: true
    }
});

//You will sometimes see this. Yuck.
PurchaseOrder.prototype = new Order(); //prototype inherits functionality
//constructor is a reference to what was used to create, otherwise the constructor of PurchaseOrder is Object
PurchaseOrder.prototype.constructor = PurchaseOrder; 

Even Better Object Definition

function PurchaseOrder(){
    var id = 'BB3445';
    
    Object.defineProperty(this, "id", {
        get: function(){
            return id;
        },
        set: function(val){
            id = val;
        },
        enumerable: true,
        configurable: true
    });  
}

PurchaseOrder.prototype = {
    constructor: Order, //DO NOT FORGET TO DO THIS IF YOU USE THIS PATTERN 
    print : function(){
        console.log('Checking paper...');
    },
    ship : function(){
        console.log('Send to place...');
    }
}

Another way to use prototype

The constructor is defined on the prototype. Not the function.

Comparing Types of Objects

function Order(){
    var id = 'BB3445';
    
    Object.defineProperty(this, "id", {
        get: function(){
            return id;
        },
        set: function(val){
            id = val;
        }
    });  
}

function PurchaseOrder(){} //Define our class

PurchaseOrder.prototype = new Object(Order.prototype, {
    constructor: {
        value: Order
    }
});

//You will sometimes see this. Yuck.
PurchaseOrder.prototype = new Order(); //prototype inherits functionality
console.log(order instanceof PurchaseOrder) //true
console.log(order instanceof Order) //true
console.log(typeof order) //function, still just a function

use instanceof for comparison not typeof

Things to Remember:

  • All Object inherit from Object.prototype
  • Methods defined in the constructor are copied to each new instance
  • Prototype methods have one copy shared among all instances
  • Adding a prototype method at any point will add that method to ALL current/future instances of that object
  • Private variables should be in your constructor, not the prototype

All the OOP - ES5 Edition

By Jason Sewell

All the OOP - ES5 Edition

The basics of ES5 OOP and basic usage of prototypes.

  • 2,704