Monday, December 2, 2013

Function Invocation

Javascript functions can be invoked in four ways:
functions,
methods,
constructors,
call() and apply()

They differs from each other in various ways, and most importantly in invocation context and returning mechanisms.

First of all, let's introduce a definition called invocation expression. An invocation expression consists of a function expression that evaluates to a function object followed by an open parenthesis, a comma-separated list of zero or more argument expressions, and a close parenthesis.

Now let's dive into each type of function invocation one by one. The first one is called Function Invocation. When a function is invoked as function, it's invoked using invocation expression.  The line
sum(1, 1); in the example below is a function invocation. It has the function expression sum, an open and close parenthesis and argument expressions 1, 1.

function sum(x, y){
  console.log('The sum of x and y is '+ (x+y))
}

sum(1, 1);

Method invocation is similar. It's just a function stored in a property of an object. Specify the object on which this method is called before the invocation expression when you invoke a method. See the example below. calculator is the name of the object and add() is the invocation expression. Any function that is used as method is effectively passed an implicit argument - the object through which it is invoked.

var calculator = {
  operator1: 1, 
  operator2: 1, 
  add: function(){
    console.log('The sum is '+(this.operator1+this.operator2));
  }
}
calculator.add();

If a function or method invocation is preceded by the keyword new, then it is a constructor invocation. A constructor invocation creates a new, empty object that inherits from the prototype property of the constructor. 

var arr = new Array(); //By convention, constructors start with capitals

Javascript functions are also objects. It has its own methods. Two of them are called apply and call, which can be used to invoke the function indirect, and by using them, you can also specify the invocation context as the first argument. See example below.

function sum(x, y){
  console.log('The sum of x and y is '+ (x+y))
}

sum.call(undefined, 1, 1);
sum.apply(null, [1, 1]);

Invocation Context for different types of function invocation.

Non Strict ModeStrict Mode
Function Invocationglobalundefined
Method Invocationthe caller objectthe caller object
Constructor Invocationthe new objectthe new object
Indirect Invocationcan be specifiedcan be specified

Sunday, December 1, 2013

Javascript - Why Assign this value in self

In Javascript, we see this line of code frequently
self = this;

We know this refers to the invocation context, but why we need to assign its value to a variable. The reason is this keyword does not have a scope, and nested functions do not inherit the this value of their caller. Thus if a nested function is invoked as a function, its this keyword actually refers to global object (non-strict mode) or undefined (strict mode). In order to access the invocation context of the outer function, we need to assign the value of this keyword to a variable. Recalling from our previous blog Variable Scope & Function Scope, we have variables are visible within the function in which they are defined and within any functions that are nested within that function. Now let's take a look at the following code snippet.

var o = {
  m: function(){
    var self = this;

    console.log(this===o);   // return true
    f(); //invoking nested function as a function

    //nested function
    function f(){
      console.log(this===o);  // return false
      console.log(self===o);  // return true
    }
  }
}

o.m();