Saturday, July 5, 2014

04 - Functions as Objects

Functions in JavaScript are objects, so functions can be assigned to variables, passed to other functions as parameters, returned from other functions. Additionally, functions have their own properties.

Functions Assigned to Variables
Functions in JavaScript can be defined and assigned to variables, and then invoked via the variables, as shown in the following example:

var add = function(a, b) 
    return a + b;
};

console.log(typeof(add)); // function
console.log(add(1, 2)); // 3
An anonymous is defined, and then is assigned to variable name add.  Now the variable name add is referenced to the function, and can be invoked as the function.

Functions as Parameters
Functions can also be passed to other function as parameters, as shown below:

function calculate(operator, a, b) {
    return operator(a, b);
};

function add(a, b) {
    return a + b;
};

console.log(calculate(add, 2, 5)); // 7
console.log(calculate(multiply, 2, 5)); // 10

The first parameter of the function calculate is a function. When the function add is passed as the parameter, it adds two numbers. Otherwise it multiplies two numbers if the function multiply is passed.

When a function is passed as a parameter to another function, it is called a callback function. There are many APIs take callback functions as parameters, which provide much flexibilities to use the APIs. For example, we could pass a callback function to add up the elements of an array to the forEach method of an array, as shown below:

function sum(nums) {
    var total = 0;
    nums.forEach(function(num) {
        total += num;
    });
 
    return total;
};

var nums = [1, 2, 3, 4];
console.log(sum(nums)); // 10 

An anonymous function, which adds an element of the array to the variable total, is passed to the method forEach. When the method forEach is invoked with the callback function, the total sum of all elements in the array is added up.

Functions as Return Values
Similar to other kinds of objects, functions can also be returned from functions. As shown in the following piece of code, the function addFunc returns a function, which adds two numbers:

function addFunc(a, b) {
    return function() {
        return a + b;
    }
};

var func = addFunc(3, 5);
console.log(typeof(func)) // function
console.log(func()); // 8 

The variable func references to the returned function of addFunc, so the type of func is a function. Additionally, the function can be invoked as normal functions.

Functions with Properties
Objects have their properties. So Functions. We add a property count to the function test below:

test.count = 0;
function test() {
    test.count++;
    console.log(test.count);
}

test(); // 1
test(); // 2
test(); // 3

When the function test is invoked, the property count increases. We could implement the same functionalities with another global variable. However, the property count has some advantages, because it will not conflict with other variables. That's to say, it is OK for us to define a global count, since it will not conflict with the property test.count.

Similarly, functions can be viewed as arrays, and they can have their own elements.  As we know, it is quite time-consuming to  calculate the Fibonacci sequence recursively, if without caching. We may cache the intermediate results in the function, as listed below:

function fibonacci(n) {
    if(fibonacci[n - 2] === undefined) {
        fibonacci[n - 2] = fibonacci(n - 2);
    }

    if(fibonacci[n - 1] === undefined) {
        fibonacci[n - 1] = fibonacci(n - 1);
    }

    return fibonacci[n - 1] + fibonacci[n - 2];
}

fibonacci[0] = 0;
fibonacci[1] = 1;

console.log(fibonacci(10)); // 55
console.log(fibonacci(50)); // 12586269025

The function Fibonacci is also an instance of array. When a value of the Fibonacci sequence is calculated, it is cached into the array. It is more efficient to calculate next values based on the cached values.

No comments :

Post a Comment