Skip to content

Instantly share code, notes, and snippets.

@karanth
Last active January 2, 2016 12:29
Show Gist options
  • Save karanth/8304056 to your computer and use it in GitHub Desktop.
Save karanth/8304056 to your computer and use it in GitHub Desktop.
Notes on Javascript OOP concepts - Part 1 - All about 'this'

Basics

Creating an object in javascript is as simple as,

var obj = {};

This is also equivalent to using the new operator and calling the Object function.

var obj = new Object();

Note: The former shorthand way of object creation is suitable for creating one off objects. But for creating multiple objects of the same type, the latter (using the new keyword) is a cleaner and better way. Also, the new keyword takes care of preparing the object for use.

Under the hood Object is actually a function and the new keyword does some stuff (examined later) to return an object var. Objects in OOP are operated by interface/public/privileged methods. These methods can be called from outside the object. In contrast, there are private methods, methods that can be called from within the object only. Objects in OOP can also have private member variables and public properties. Private member variables provide encapsulation and like private methods are visible only from within the object, while public properties can be modified externally. Let us take an example and look at how these concepts manifest in Javascript.

function Car(numberOfCylinders, carType){

  //Private member variables. They can be set only during object construction.
  var type = carType;
  var cylinders = numberOfCylinders;
  var volumeOfCylinder =  250;
  var self = this;
      
  //Private member methods. They can be called only from within the object i.e. from within the constructor
  //or any other function within the object.
  var getCC = function(){
                return cylinders * volumeOfCylinder * self.turboFactor;
              };

  //Public properties. These properties can be set from outside the object.
  this.color = 'White';
  this.sunRoof = false;
  this.turboFactor = 1;
  
  //Interface/Privileged method
  this.start = function(){
                  //Note the use of a  private method
                  console.log('The car with ' + getCC() + ' engine and color ' + this.color + ' is starting...');
              }

  this.stop = function(){
                  console.log('The car has stopped');
                  }
                  
}

The main distinction between privately and publicly permissible properties or methods is the usage of the var vs the this keywords. The var keyword makes a property or method private and visible only to code within the object, but the this keyword makes it visible internally and externally. The this keyword gives a handle to the current object.

To create a Car object it is as simple as the code below,

var honda = new Car(4, 'sedan');  //creates a new object and calls the constructor. Initializes this too
honda.start();  //The car with 1000 engine and color White is starting...
honda.stop();

Internals - this

Let us now examine the this keyword in depth and figure out what it does under the hood.

The this reference provides context to function execution. It is a property of a Javascript function. Just like an Object has properties and methods, functions in Javascript also have properties.

The this reference is inferred and assigned only when the function that contains it is called.

In other words, it gets initialized at the latest possible instant and that is when the function is executed.

Let us look at 2 different classes of scenarios where the this keyword can cause issues. The example assumes that the javascript is loaded on a browser web page:

var honda_start = honda.start;
honda_start(); //The car with 1000 engine and color undefined is starting...
  • When a global function containing this reference is called, this points to the window object of the browser. In the example above, when we extract the start method and call it in a global context, the color property is no longer defined. A similar problem exists when object methods are passed as callback handlers. An example could be passing an object method as a click handler that is called on clicking a button. When the button invokes the callback function, the context during execution of the handler is the button object or in other words, the this reference within the callback function has a different reference (that of the button and not that of the original object). This problem can be mitigated by using the call, bind or the apply methods defined on the Javascript Function object.

  • When this is referenced by an inner method (anonymous or otherwise) or a closure, this is not bound to the reference of the outer method.The inner method acts like a global function. In the above example, the private method getCC is invoked by the public method start but executes in the global context. If this was used in the getCC method instead of self to reference the object (encouraged to try it out), it would've led to an error as it has not inherited the this reference from the invoking function. These problems can be mitigated by assigning the this reference of the outer method to another var that is referenced from the closure. Generally, self and that are used as names of variables that reference the outer method's this reference. Another option to mitigate this particular scenario is to use the bind function. The bind tells the function to use a particular reference as this when the function is executed.

We will look at the internals of the new operator in the next part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment