Saturday 6 September 2014

Functions in Javascript - Behold The Prime

In this post we take on the topic which makes Javascript an off roader as against a sedan(like C#, Java).  The analogy might not be apparent but in my opinion an off roader has all the capabilities of a sedan (read luxury, comfort) plus it gives you greater power and maneuverability provided the drivers knows how to tame the beast.

In my mind Javascript provides us developers same features of any 4G language however it’s us who needs to adapt to getting best out of it.

So what makes functions in Javascript special or rather lets ask our self what is a function?

Well a function in my mind is a set of code which can be called using a name and performs certain pre-defined set of operations using the arguments passed and may return a value (*).

So how are functions in Javascript different?

Well again in my humble opinion a function in Javascript is a normal function on steroids :) , lets see the characteristics of a function in Javascript
  • its an object (we will get into this later), 
  • its a function for sure, 
  • it can be passed to any other function (so what that's also in C#/Java), 
  • it can be returned from a function (again same can be achieved in C#/Java) and 
  • it can be stored in a variable (puff we all know pointers in C)
However what makes function in Javascript truly First Class Citizen is its dynamic nature (as against of object being the first class citizen in C#/Java)

In C# we again need to define a Func or an Action (thus a predefined signature), however no such restriction exists in Javascript ( I don't know about Java but I am sure these features must exists)

Storing function in variable:

Below we tossed around the pointer to function Add(pointer is loosely used here as in Javascript there is no concept of pointers).

 function Add(number1,number2){  
   return number1+number2;  
 }  
 console.log(Add(5,5)); //10  
 var funcAdd = Add;  
 console.log(funcAdd(5,5)); //10  
 var anotherFuncAdd = funcAdd;  
 console.log(anotherFuncAdd(5,5)); //10  

Passing a function as an argument

This can be easily achieved

 function DoSomething(someFunc, someAgrs){  
   return someFunc(someAgrs);  
 }  
 var func = function IncrementByOne(val){  
   return val+1;  
 }  
 console.log(DoSomething(func,10)); //11  

Did you noticed closure here?

Returning a function and executing same.


 function DoSomething(args){  
   var val = args;  
   return function IncrementByOne(){  
     return val+1;  
   }  
 }  
 var func = DoSomething(10);   
 console.log(func()); //11  

Overloading functions:

What happens if we do following

 function Add(number1,number2){
   return number1+number2;
 }
 //Overload the function Add
 function Add(number){
   return 'Get out of here!';
 }
 console.log(Add(5,5)); //Get out of here!

As you can see we can't overload a function you may ask why remember the earlier post that during the creation of the EC(execution context), for each function in context create a property which points to the function and if the functions name is same then the property is overwritten.

Thus the later occurrence of the Add function overwrites the property pointing to the earlier Add function.

Function Declaration/Function Expression

Just a recap between function declaration and function expression
 //Function Declaration  
 function Add(num1,num2){  
   return num1+num2;  
 }  
 //Function Expression  
 var add = function(num1,num2){  
   return num1+num2;  
 }  

We have already discussed about Hoisting and how function declaration are hoisted  as against expressions.

Function Internals

Now this is important, two special objects exists inside a function arguments and this, agruments is an array like object which contains all the parameters passed to the function, along with a property called callee which is a pointer to a function which own the arguments object (basically function itself)

this: we have discussed about same in our last post but lets have a quick recap. this in Javascript unlike C#/Java does not refer to the current executing function rather to the current executing context.
this refers to the context in which the currently executing function was called.

 name ='Pankaj';  
 var Person = {name:"Lala"}  
 function showName(){  
   return this.name;  
 }  
 console.log(showName()); //Pankaj  
 Person.showName = showName;  
 console.log(Person.showName()); //Lala  

First call to showName happened under the context of global object and the second call was made under the context of Person.

Functions also have a property called caller, which is the function which called the function. In case of call originating from global the value of caller will be null.

 function Outer(){  
   return inner();  
 }  
 function inner(){  
   return 'Pankaj called by function:' + inner.caller;  
 }  
 console.log(Outer());  
 /*  
 Pankaj called by function:function Outer(){  
   return inner();  
 }*/  

Function Properties/Methods

length property gives the count of arguments passed to the function

 function func(name,age,sex){  
   //  
 }  
 console.log(func.length); //3  

prototype: lets leave this for our next post(s).

call() & apply()

If I say a function was invoked it makes sense but when I say call a function still one could make sense of same but as soon as we mention apply the function it sounds a bit weird (at least it did to me)

Given that the part played by the calling context when a function was executed, these above methods gives us the power to execute a function and also to pass in the context we want them to be executed in.


All hail functions :)

Let's revisit our earlier example for this,

 name ='Pankaj';   
  var Person = {name:"Lala"}   
  function showName(){   
   return this.name;   
  }   
  console.log(showName());   
  Person.showName = showName;   
  console.log(Person.showName());   

What if I tell you that Person.showName= showName is redundant and Javascript has more elegant way to doing this thing. Lets modify our code as shown below

 name ='Pankaj';   
  var Person = {name:"Lala"}   
  function showName(){   
   return this.name;   
  }   
  console.log(showName());   //Pankaj
  console.log(showName.call(Person)); // Lala


Yeah man its keep on getting better. Now go back and read the phrase for call and apply again. Here we passed Person (context) under which we wanted to invoke getName(function).

Now on a higher level apply achieve same thing, then what is the difference. Difference is the second argument which these methods  take.

call as its second argument takes the named arguments which needs to be passed to the invoking function

apply as its second argument takes the list of the arguments which needs to be passed to the invoking function.

In our example its imperative if we use call or apply as we are not passing the second argument. Jsfiddle it and see it for yourself.

Thus the advantage these methods bring to the table is that they help us augment the scope without the object knowing it.

Mind it people this is a very trivial example and these methods are very powerful so we sure will be visiting them again.

You may have noticed that I used keyword function and method, in Javascript they are not the same. In my next post I will take up the topic of OOP in Javascript and there I will try to shed more light on this topic, till then stay tuned and happy scripting.


1 comment: