Friday, 25 September 2015

In Detail: Functions In JavaScript

Functions In JavaScript:

Just like other variables, Functions in JavaScript are just values. All the functions you define are instances of Function. first let's see how create a function.

Creating / Declaring a function:
function echo(x) {

   return x;

}
typeof echo; // "function" 
keyword to define function is "function". Remaining syntax is similar to functions/methods in other programming languages just like C, C++, Java.

A function in JavaScript

1. can accept parameters,
2. can return values,
3. doesn't need an explicit return type.
4. returns "undefined", if you don't return anything from a function.

Calling a function:

Like in other programming language, you can call / invoke the function with it's name by passing parameters if any. for example,
echo("hello"); // hello

echo(1); // 1
A function in JavaScript can play different roles. Based on the context and usage, it can act

1. As a normal function just like in above examples,
2. As a constructor, a factory for objects,
3. As a method, i.e as a property of an object.

As a normal function:

if you call the function directly with required parameters, then it works as a normal function. for ex:
echo("hello");// return hello
As per JavaScript naming conventions, all normal functions start with lowercase letters.

As a Constructor:

If you invoke a function via the new operator, then it becomes a factory for objects. For ex:
function echo(x) {

   return x;

}
var obj = new echo("abc");

typeof obj; // object.
As a Method:

You can store a function as a property of an object, which turns it into a method that you can invoke via that object. For ex:
var obj = {}; // empty object

obj.echo = function(x) { return x; };

obj.echo("abc"); // abc
As per JavaScript naming conventions, names of methods start with lowercase letters.

As mentioned all the functions are instances of Function. You can check it with the below code
function echo(x) { return x; }

echo instanceof Function; // true

Different ways to create a function:

you can create a function in 3 ways.

1. Using a function expression.
2. Using a function declaration.
3. Using the constructor Function();

Using function expressions:

Just like other expressions, a function expression gives a value - i.e a function object. For ex:
var add = function(x,y) { return x+y; };
add(2,3); // 5
Here the function add takes 2 arguments and return their sum. Because of no name, they are also called as anonymous function expressions.

You can also give a name to function expression. They are referred as Named function expressions. This allows a function expression to refer to itself, which is useful for self-recursion. For ex:
var factorial = function fac(n) {
  if(n > 0) {
        return n * fac(n-1);
  } else {
       return 1;
   }
};
console.log(factorial(3)); // 6
Note: name of a named function expression is accessible inside the function expression only.

Using Function declarations:

Following is a function declaration.
function add(x,y) {
   return x+y;

}
it looks like a function expression, but it is a statement. What goes behind the scenes is, it declares a new variable, creates a function object, and assigns it to that variable.

Using Function Constructor:

You can define a function using Function constructor just like below.
var add = new Function('x','y','return x+y');
Here we are passing function parameters and function body to the constructor. However, this way of defining a function is slow and keeps function body in strings. Therefore it is much better to use a function expression or a function declaration if possible.

Note: JavaScript moves all the functions declared to the beginning of the scope, this is called as hoisting. For ex:
echo(5); // calling echo before it's creation

function echo(x) { return x; } // function echo created here.
Now JavaScript engine moves the declaration of function echo to the beginning of the scope. The above code execution is as follows.
function echo(x) { return x; } // function echo is hoisted

echo(5); // 5 
Which one to choose: A function declaration or a function expression:
A function declaration and function expression both are basically the same, but function declarations have two advantages over function expressions.

1. They are hoisted, so you can call them before they appear in the source code.
2. They have a name. 

Default methods of all Functions:

As all the functions defined by user are instances of Function, so the methods call(), apply() and bind() are accessible to these.

These methods are mainly interested in Object-oriented context.

apply(this, argArray):

first lets see with an example,
Math.max(17, 33, 2); // returns 33

Math.max.apply(null, [17,33,2]); // returns 33
In the above example, both calls are valid and produce same result. It is useful, when a function accepts multiple arguments and you get all arguments as array, in such cases, you can simply invoke apply instead of actual method. 

here argument this is "JS this value of an Instance".

bind(this, arg1,...,argN):

I am going to explain bind() with an example,
function add(x,y) {

    return x+y;
}
var plus = add.bind(null,1);

console.log(plus(5)); // 6
here argument this is "JS this value of an Instance".Here we made argument x to be 1 always.

It is equivalent to the following code
function plus(y) {
   return add(1,y);
}
How to handle Missing or Extra parameters:

In JavaScript, you can call a function by passing any number of parameters. you can pass more or fewer parameters than the parameters defined in function definition.

If you pass more parameters, the extra parameters are ignored but you can retrieve those via special variable "arguments".

if you pass fewer parameters to the function, the missed parameters all have the value undefined.

The special variable "arguments":

The special variable arguments exists only inside functions(including methods). It is an array-like object that holds all of the user passed parameters of the current function call. for ex:
function add() {
   var sum = 0;

    for(var i = 0; i < arguments.length; i++) {

         sum += arguments[i];
    }

    return sum;

 }
It has the following characteristics:

1. It is array-like, but not an array. On one hand, it has length property, and individual parameters can be accessed by index.
2. On the other hand, it is not an array, it has none of the array methods such as slice(), forEach(), etc. But you can borrow array methods or convert arguments to an array.
3. It is an object, so all object methods and operators are available.For ex, you can use in operator to check whether arguments has a given index
  function f() { return 1 in arguments; }

  f('a'); // false

  f('a','b'); // true 
4. You can use hasOwnProperty() in a similar manner
function g() { 
   return arguments.hasOwnProperty(1); 
}
g('a','b'); // true

Naming the parameters:

When calling a function in any programming languages, you must map the actual parameters (specified by the caller) to the formal parameters (of a function definition). To do this we have two ways.

1. Mapping the parameters by position, here the first actual parameter is mapped to the first formal parameter, the second actual to the second formal and so on.
2. Mapping the parameters by name i.e named parameters. Here, we label the actual parameters (from caller) with a name. It doesn't matter in which order named parameters appear, as long as they are correctly labelled.

Let's see an example of named parameters in Python programming language to get more clarity.

Let's say you have a function, getAddition(), that adds values and returns sum. Given the function call:
getAddition(10,20,30);
As python supports named parameters, you can invoke the function just like below.
getAddition(param1 = 10, param2 = 20, param3 = 30);
param1, param2, param3 are names of formal parameters.
But JavaScript doesn't have native support for named parameters like python and many other programming languages, but you can achieve in different way i.e using object literal.

you can call the above function in Js as
getAddition({param1:10, param2:20,param3:30});
you can also omit any of them.
getAddition({param1:10});
getAddition({param2:20,param3:30});
getAddition();
you can also combine positional parameters with named parameters. it is customary for the latter to come last:
getAddition(posParam1,posParam2,{namedArg1:10});


0 comments:

Post a Comment

Note: only a member of this blog may post a comment.