showtext();
}
myFunction();
Here, the outer and inner functions are myFunction and showtext, respectively. A variable mytext is defined in myFunction. The inner function showtext is declared within myFunction. The showtext function is then called. When the function myFunction is called, the output in the console is as shown in Figure 7-10.
Figure 7-10. Program output Figure 7-9. Program output
Lexical Scoping
In the context of functions, lexical scoping means that the scope of a variable is determined via the location of the variable within the JavaScript source code. Any variables that are declared outside of functions are accessible and visible to the entire JS program (i.e., global variables). On the other hand, variables declared within a given function are only visible and accessible to the code block of the function in question. This is called function scope. In the case of nested functions, the inner function has access to variables declared in the outer function. Any variable declared in the inner function may not be accessed outside of it.
Chapter 7 ■ Doing More with FunCtions
Consider the example of lexical scoping in Listing 7-11.
Listing 7-11. Lexical Scoping Example function myFunction() {
var mytext = "Mytext";
function showtext() { console.log(mytext);
}
showtext();
}
Function myFunction declares a local variable mytext and a function showtext—the inner function defined inside myFunction() that is available only in the body of myFunction. Here, showtext has no local variables, but it has access to those of its outer functions, in this case myFunction. Within the myFunction body, the showtext function is called in order to display the text contained in variable mytext.
Let’s consider another example of lexical scoping in Listing 7-12.
Listing 7-12. Second Lexical Scoping Example
<html>
In this example, variable function1 is assigned to a function. Within this (outer) function is a variable text1 and an inner function f2. Within the inner function there are two if statements and two blocks (shown in curly brackets).
The variable text2 is accessible anywhere within the function f2, irrespective of the code block in which it is declared. However, text2 is not accessible outside the function f2. Hence, the error results with
Chapter 7 ■ Doing More with FunCtions
106
Closures
Under normal circumstances, the local variables within a function only exist for the duration of that function’s execution. After the function has executed, the local variables normally can’t be accessed.
However, it is possible to have local variables persist after the function’s execution by using closure.
In JavaScript, you can create special functions known as closures that remember the environment (state) in which they were created. These include independent local variables within the function. So, in other words, a closure is composed of
• A function
• The environment of the function
Environment in this context means the local variables at the time of closure creation. Consider the non-closure example in Listing 7-13 that produces a syntax error.
Listing 7-13. Syntax Error function myFunction() { var num = 10;
}
console.log(num);
This generates a syntax error because num is not accessible to the outside world. However, by using closure, num can be accessed. Consider the example in Listing 7-14.
Listing 7-14. Closure Example function Func() {
var num = 10;
function returnnumber() { return num;
When this code is executed, the output is as shown in Figure 7-11.
Figure 7-11. Program output
The number will be displayed in the console of the browser. The inner returnnumber function was returned from the outer function Func before execution. Func has become a closure. In this case, Func is a closure that contains both the function and the num value 10 that existed at the time of closure creation.
Chapter 7 ■ Doing More with FunCtions
Listing 7-15 shows an example with a more useful purpose.
Listing 7-15. Division Using Closure
<html>
<body>
<script>
function divisionfactory(divisor) {
return function performdivision(number) { return number / divisor ;
} }
var divideby10 = divisionfactory(10);
var divideby20 = divisionfactory(20);
console.log(divideby10(100));
console.log(divideby20(200));
</script>
</body>
</html>
This example defines a function divisionfactory that takes as input a parameter divisor and returns a reference to another function. The inner function is called performdivision (though you could have this as anonymous as well). The inner function has a single parameter, number, and returns the result of the division number / divisor. As the name suggests, the outer function divisionfactory is used to create functions that can be used to divide the inputted number with a specific value.
For the sake of the example, Listing 7-15 creates two functions, divideby10 and divideby20, that divide their argument by 10 and 20, respectively. These two new functions are closures that have a similar body but separate environments. For divideby20, the value of divisor is 10, whereas in the case of divideby10, the value of division is 20.
The output of Listing 7-15 is shown in Figure 7-12.
Figure 7-12. Division output
Chapter 7 ■ Doing More with FunCtions
108
Consider another interesting example of closure in Listing 7-16.
Listing 7-16. Another Closure Example var add_element = (function() { var total_elements = 0;
var array = [];
return function addition(element) { array[total_elements] = element;
This example defines a function and assigns it to the variable add_element. Within the code, the variables total_elements and array are declared with initial values of 0 and [ ], respectively. The property element is assigned to the end of the array array. In addition, the total_elements counter is incremented by 1 upon each insertion of element to array. This function returns a function addition that adds a new element passed to it to the array and increments the count of elements in the array.
The example in Listing 7-16 calls add_element three times, supplying values 10, 11, and 12, respectively.
The output of Listing 7-16 is shown in Figure 7-13.
Figure 7-13. Program output showing array elements
The add_element is a closure that contains the function addition. However, because Listing 7-16 uses a self-invoking function, the initialization statements (setting array to [] and setting total_elements to 0) are executed only once. As you will see, each function closure remembers the state in which it was created.
These include the variables array and total_elements.