JavaScript 101: Advanced Functions

Reading the chapter on advanced functions in Head First JS. JavaScript has some really powerful function capabilities - with the option to do pretty advanced stuff with functions.

Anonymous Functions
Have encountered them earlier in jQuery, while defining callbacks for network calls. When you declare a function, it is given a name by default. However when you use function expressions, you need not give the function a name. This is useful when you are writing a function which will not be called again in code, handlers, for example.

Nested Functions
JavaScript supports nested functions. That means you can declare a function in a function and use it as a local variable:
function quack(num) {
    var sound = "Quack";
    var quacker = function() {
       console.log(sound);
    };
    for (var i = 0; i < num; i++) {
        quacker();
    }
}

The rules for when you can refer to a function are the same within a function as they are at the top level. That is, within a function, if you define a nested function with a declaration, that nested function is defined everywhere within the body of the function. On the other hand,  if you create a nested function with a function expression, then that nested function is defined only after the function expression is evaluated.

Lexical Scope
Scope refers to the area in the program in which the variable is visible. The technique used to determine scope in JS is lexical scoping, meaning that you can tell the value or the scope of a variable by just looking at it's place in the program code, you don't need to wait for execution. Let's see an example:


var myVar = "hello!";    //global variable
function outer() {       //a function
    var myVar = "hi!";   //local variable which shadows global
    function inner() {   //inner function
        return myVar;    
       //it can refer to myVar as it is in enclosing function
    }
    return inner;       //returning reference to function
}

var innerFunc = outer();  //getting reference of inner function
var val = innerFunc();    //what will be returned?
//val now contains "hi!", not "hello!"


Mind = Blown!
If this was Java, or C, or any other language with dynamic scoping, here's how things would have happened: As the inner function is called from outside the outer function, and a variable named myVar exists in global scope, it would surely have returned that value.
But not so in JS! Lexical scoping follows the simple rule: To determine the value of a variable, we look at the nearest function scope. If it is not to be found there, it must be in global scope.
So here, take a look at definition of inner(). It is returning myVar. Which version? Apply our rule. Start from inside and move outside. The nearest myVar is in outer(). Hence, this is the one that will be returned. This is the basic idea of Lexical scoping, and in my opinion, is simpler than dynamic scoping.
 

No comments:

Post a Comment