Reliable JavaScript Certification Online #

Function is a defined block of code that performs specific tasks and can be invoked and executed many times.
Functions in JavaScript allow you to extract piece of code, give it a name and reference to it wherever it is needed.

 

Function definition

JavaScript function can be defined using a function declaration statement or as a function
definition expression.

Function declaration statement

Function definition begins with the function keyword followed by the function name, pair of round brackets inside of which there is a list of zero or more parameters and pair of curly brackets with zero or more JavaScript statements inside.

function info(name, surname) {
    var message = "Hello " + name + " " + surname;
    alert(message);
}

Function declaration statement is like declaration of a variable and assigning a function object to it.
Function name can be any valid JavaScript identifier. Then you can use this name to refer to that function in the code.

Function definition expression

In this case a function is defined as a part of an expression. Function definition also begins with the function keyword. Function name is optional, the rest is the same as in the function declaration.

var info = function (name, surname) {
    var message = "Hello " + name + " " + surname;
    alert(message);
};

Function defined using function declaration expression can be assigned to a variable or can be used only once in an expression. If you assign function to a variable, at the end of the expression put a semicolon. You can use this variable to refer to that function in the code.

Function expression can be immediately invoked:

var repeatedCharA = (function (length) { var s = ''; for (var i = 0; i < length; i++) { s += 'A'} return s; }(8));

Anonymous functions

Functions used as a function expression without a name are called anonymous functions.

Scope of functions

Functions defined both ways have different scope.
Functions defined using declaration statement are hoisted to the top of the script or enclosing function. Therefore they can be invoked in the code above the place, they are declared.
Functions defined as expression cannot be invoked before they are defined. Assignments to variables are not hoisted.

Return statement

Functions not only execute a code defined inside their body but also can return value by using the return statement. If the return statement has an associated expression, value of this expression is returned. Otherwise it returns the undefined value.
Also if a function does not have the return statement it returns the undefined value.
Note that using the return statement it is possible early termination of function, for example if if the condition is not met.

function calculateBmi(weight, height) {
    if (!weight || !height) {
        return;
    }
    var bmi = weight / height * height;
    return bmi;
}

Nested functions

Functions in JavaScript can be nested inside other functions.

function calculations(val1, val2, val3) {
    function multiply(val1, val2) {
        return val1 * val2;
    }
    var result = multiply(val1, val2) + multiply(val1, val3) + multiply(val2, val3);
    return result;
}

Nested functions have access to the parameters and variables of the enclosing function.

 

Invoking functions

The function definition itself does not execute its code. To execute a function code you need to invoke it. There are several ways how functions can be invoked.

Function invocation

To invoke a function specify the function providing its name or a variable to which the function was assigned. Then add a pair of round brackets inside which put a comma-separated list of zero or more arguments.

info('James', 'Doe'); 
var amount = calculations(2, 4, 5);

Values passed as arguments are assigned to the function parameters. Then the code in the body of the function is executed. The value of the return statement is the value of the invocation expression.

Method invocation

A method is a function stored in a property of a JavaScript object.

var myObject = {};
myObject.func = function (message) {
    alert('User sent a message: ' + message;
}

To invoke a method refer to the object followed by dot “.”, followed by the method name and a pair of round brackets and list of zero or more arguments inside them.

myObject.func('hello');

Method invocation works in the same way as function invocation. The main difference is the invocation context. The context for a method is the object that calls it. In the function body you can refer to that object using the keyword this.

var calculation = {
    factor: 2,
    multiply: function(value) {
        return value * this.factor;
    }
};

var result = calculation.multiply(5); // returns 10

The this keyword is not however inherited by nested functions. If nested function uses the this value, it does not refer to outer function context but it will be either global object or undefined (in strict mode).
That is why you should store the this value in a variable eg. the that variable and refer to it in a nested function to get the this value:

var obj = {
    meth: function() {
        var that = this;
        func();
        
        function func()
        {
            console.log(obj === this); // false
            console.log(obj === that); // true
        }
        
    }
};

Method chaining

Method invocation uses property access expression and may be more complex:

An object can contain another object whose method you want to call:

vehicle.engine.start();

You can invoke a method that returns an object, then you can directly invoke another method on it:

store.getItem('camera').deduct(1);

In this way you can invoke chain of methods as a single expression.

If methods of an object return the this value, then you can name this object once and call multiple methods on it:

rectangle.setX(100).setY(50).draw();

Constructor invocation

Functions may be used to create objects. If a function is preceded by the keyword new then it is a constructor invocation.

var myObject = new MyObject();

If a constructor does not have parameters, then you can omit parentheses.

var myObject = new MyObject;

A constructor invocation creates a new object and the constructor function initializes it. The new object is the invocation context and constructor can refer to it using the this keyword.

Constructor functions usually do not use the return keyword. They initialize a new object and this object is the value of the constructor invocation expression. If a constructor explicitly returns an object, then that object is the value of the constructor invocation. If it returns a primitive value, this value is ignored and the new object is the value of the invocation.

 

Function parameters and arguments

Function parameters

Function can be parameterized. It means that in the definition of a function you define parameters in parentheses and use them in the function body:

function publish(title, content) {
    console.log("Title: " + title);
    if (content) {
        console.log("Content: " + content);
    } else {
        console.log("No content");
    }
}

In the function above the title and the content are parameters. That allows you to call the function many times with different values passed to it.

Function arguments

Values passed into an invoked function are called arguments:

publish("Game of thrones", "The woods began to grow dark...");
publish("The Lord of the Rings", "The world has changed...");

These arguments match parameters from the function definition.

To the function can be passed any JavaScript value like numbers, strings, objects. Function definition does not specify an expected type for its parameters. Function invocation even does not check if the number of passed arguments fits the number of parameters in function definition.

If the number of passed arguments is smaller than defined parameters, then parameters for missing arguments are set to the undefined value.

function myLog(a, b) {
    console.log('val a: ' + a);
    console.log('val b: ' + b);
}

myLog('ok');

// Output:
// val a: ok 
// val b: undefined

JavaScript has no formal definition of optional function parameters, but you can specify them in the function body using the || operator:

// here b is an optional parameter

function doCalculations(a, b) {
    b = b || 1;
    var result = 2 * a * b;
    return result;
}

The || operator returns the first argument if it is true or the second argument otherwise.

The arguments object

The arguments object allows you to read all passed arguments in the function invocation. This is useful when the number of passed arguments differs from the number of defined function parameters, especially when it is bigger. The arguments object is like an array and contains a numerical list of arguments in the order in which they were passed.

function add(x, y) {
    var result = 0;
    if (arguments.length == 2) {
        result = x + y;
    } else {
        for (let i = 0; i < arguments.length; i++) {
            result = result + arguments[i];
        }
    }
    return result;
}

var result = add(3, 5); // 8
var result2 = add(3, 5, 6); //14

If a function has defined two parameters x and y and you pass three arguments, then you can read two first arguments using parameters names x and y or using arguments[0] and arguments[1]. The third argument is accessible only as arguments[2].

Arguments pass by value

Arguments in JavaScript are passed to function by value. It means that argument is copied into parameter variable.
Consider following example:

function increment(val) {
    val = val + 1;
}
 
var size = 3;
increment(size);
console.log(size); // 3

In case of code execution above value of size is copied into parameter val and then val is incremented. However value of size does not change and remains equal to 5.

 

Functions as values

The standard features of functions in programming are their definition and invocation. In JavaScript functions are also values. They can be assigned to variables, objects properties or arrays elements.

Consider the following function definition:

function multiply(x, y) {
    return x * y;
}

This syntax means definition of a new function. More specifically a new function object is created and assigned to the variable multiply.

This function can be assigned to a variable and still will work:

var operation = square;
var result = operation (3, 7); // 21

You can assign it to an object property:

var calculator = {};
calculator.multiply = function(x, y) { return x * y; };
var result calculator.multiply(3, 2); // 6

In a similar way you can assign the it to an array element:

var calc = [];
calc[0] = function(x, y) { return x * y; };
var result = calc[0](2, 4); // 8

Function can be passed as an argument to another function:

function calculations(a, b, operation) {
    a = parseInt(a);
    b = parseInt(b);
    return operation(a, b);
}

var result = calculations('2', '5', function(x, y) {
    return 2 * (x + y);
}); // 14

 

Function namespacing

Variables defined outside of a function are global and are visible throughout JavaScript program. Whereas variables defined inside a function are local and are not accessible outside this function.

var result;
var width = 5;
 
function calculateArea() {
    var length = 10;
    var area = width * length;
    return area;
}
 
result = calculateArea();
 
console.log(width); // 5
console.log(length); // undefined
console.log(result); // 50

Here the scope of the width variable is global and it is accessible inside the calculateArea() function, whereas the scope of the length variable is local and it is accessible only inside the body of calculateArea() function.

Notice that if you declare a variable without the var keyword this variable will be global.

function getHalf(value) {
    temp = 2;
    return value / temp;
}
 
var half = getHalf(10); // 5
console.log(temp); // 2

So if you for the first time use variable inside a function without the var keyword it will be global and accessible outside this function. To avoid creating unintentional global variables, inside functions you should declare variables with the var keyword.

 

Closures

In JavaScript there are three scopes: global, block and local. Scope is a space where variables and functions are visible. Variables from global scope are accessible everywhere in the program. Variables from block scope are accessible in the block. Local variables are accessible inside a function.

Scope chain

In JavaScript global scope does not have access to local scopes (variables from local scopes. Similarly is with nested functions: the outer (parent) function has no access to the local variables of the internal (children’s) functions. However child scope has access to its parent scope. Similarly local scope has access to global scope. So if a variable to which you refer in a local scope is not found there it will be searched in parent scope. If not found in parent scope it will continue to search in parent of parent up to the global scope until it finds the variable. The ability of child scope to have access to its parent’s scope is called as a scope chain.

So in nested functions, the inner function has access to the local variables and functions of the outer function that contains it.

var outerVar = 'Global variable of the outerFunc()';

function outerFunc() {
   var outerVar = 'Local variable of the outerFunc()';
   
   function innerFunc() {
       return outerVar;
   }
   
   return innerFunc();
}

var result = outerFunc(); // the result is 'Local variable of the outerFunc()'

When you call the outerFunc() function then the InnerFunc() function is invoked. The InnerFunc() has access to local variables of the outerFunc() and the value of the outerVal variable is returned.

JavaScript uses lexical scope. It means that functions use the variable scope where they were defined not where they are executed.

Consider the following example:

var outerVar = 'Global variable of the outerFunc()';

function outerFunc() {
   var outerVar = 'Local variable of the outerFunc()';
   
   function innerFunc() {
       return outerVar;
   }
   
   return innerFunc;
}

var myFunc = outerFunc();
var result = myFunc(); // returns 'Local variable of the outerFunc()'

In this case the innerFunc() is not invoked inside the body of the outerFunc() but it is returned by this function. The innerFunc() function is invoked in the global scope, where the global outerVar variable is available. However in lexical scope it matters the structure in which the function is defined. That is why again it is returned the value of outerVar variable set in the outerFunc() function instead of in the global scope.

A closure is a function together with the environment attached to it. The environment is like a dictionary that maps variables to values by name and contains variables from enclosing scope. In other words closure is an inner function that has access to an outer function’s variables.

An example of using closures:

Imagine you need a counter and build it the following way:

var count = 0;

function counter() {
    count = count + 1;
    return count;
}

The issue here is that you use there the count variable that is global and can be overwritten by another code.

Better solution would be use local and protected variable. You can achieve this with closures:

function counterBuilder() {
    var count = 0;
    
    function counter() {
        count = count + 1;
        return count;
    }
    
    return counter;
}

var myCounter = counterBuilder();
console.log(myCounter()); // 1
console.log(myCounter()); // 2

 

Arrow functions

Arrow functions are a shorter syntax for writing function expressions. They use the => token and make the code more concise. Arrow functions are anonymous and do not have its own this, arguments and super. They are best suited as one-line functions and cannot be used as constructors.

Syntax is as follows:

(param1 [, paramN]) => { statements }

Parentheses are optional if a function has only one parameter:

param => { statements }

If a function has no parameters you should use a pair of parentheses:

() => { statements }

An example of use:

var numbers = [1, 3, 4, 7];

// Arrow function:
var numbersIncreasedBy10 = numbers.map(x => { return x + 10 }); console.log(numbersIncreasedBy10); // [ 11, 13, 14, 17 ]

// Traditional function expression:
var numbersIncreasedBy10 = numbers.map(function (x) { return x + 10 });

Arrow functions do not have its own this value, so you do not need to store it in a variable (var that = this) to use it in a nested arrow function.

 

The call() and apply() methods

The call() and apply() are function’s methods that allow you to call methods in different context as if they were methods of different object.

The call() method gives you another way of calling a method. The syntax is as follows:

function.call(thisValue [, arg1, arg2, …])

The first argument to call() becomes the value of this. All subsequent arguments are passed to the functions that is invoked.

var product = {
    unitPrice: 5,
    total: function(quantity) {
        return this.unitPrice * quantity;
    }
};

var totalProductPrice = product.total(3); // 15

You can do the same using the call() method:
var totalProductPrice2 = product.total.call(product, 3); // 15

What the call () function is useful for is to use it in a different context:

var myProduct = {
    unitPrice: 6
};

var totalMyProductPrice = product.total.call(myProduct, 3); // 18

The apply() method works in similar way as the call(). The difference is that the arguments to be passed to the function are specified as an array:

var totalMyProductPrice2 = product.total.apply(myProduct, [3]); // 18