By default, Javascript knows two types of scopes:
global and
local.
var a = 1;
function b(x) {
var c = 2;
return x * c;
}
In the above code, variable
a and function
b are available from anywhere in the code (i.e., globally). Variable
c is only available within the
b function scope (i.e. local). Most software developers won't be happy with this lack of scope flexibility, especially in large programs.
Javascript closures help solving that issue by tying a function with a context:
function a(x) {
return function b(y) {
return x + y;
}
}
Here, function
a returns
a function called
b. Since
b is defined within
a, it automatically has access to whatever is defined in
a, that is,
x in this example. This is why
b can return
x + y without declaring
x.
Variable
c is assigned the result of a call to
a with parameter 3. That is, an instance of function
b where
x = 3. In other words,
c is now a function equivalent to:
var c = function b(y) {
return 3 + y;
}
Function
b remembers that
x = 3 in its context. Therefore:
will assign the value
3 + 4 to
d, that is
7.
REM: If someone modifies the value of
x (say
x = 22) after the instance of function
b has been created, this will be reflected in b too. Hence a later call to
c(4) would return
22 + 4, that is
26.
Closures can also be used to limit the scope of variables and methods declared globally:
(function () {
var f = "Some message";
alert(f);
})();
The above is a closure where the function has no name, no argument and is called immediately. The highlighted code, which declares a global variable
f, limits the scopes of
f to the closure.
Now, there is a common Javascript caveat where closures can help:
var a = new Array();
for (var i=0; i<2; i++) {
a[i]= function(x) { return x + i ; }
}
From the above, most would assume that array a would be initialized as following:
a[0] = function (x) { return x + 0 ; }
a[1] = function (x) { return x + 1 ; }
a[2] = function (x) { return x + 2 ; }
In reality, this is how a is initialized, since the last value of i in the context is 2:
a[0] = function (x) { return x + 2 ; }
a[1] = function (x) { return x + 2 ; }
a[2] = function (x) { return x + 2 ; }
The solution is:
var a = new Array();
for (var i=0; i<2; i++) {
a[i]= function(tmp) {
return function (x) { return x + tmp ; }
} (i);
}
The argument/variable
tmp holds a local copy of the changing value of
i when creating function instances.
No comments:
Post a Comment