Good Examples For Using A Closure In Javascript
Solution 1:
Closures are used all the time with callback functions that are called some time later because they allow you to access the local variables of the host calling function or can be used to "freeze" values of local variables into private variables for a particular callback when the local variable itself will be changing to another value as the code continues to execute, but before the callback is called.
Here are examples of closures in answers I've supplied here on SO.
Access parent local variables from setTimeout callback: https://stackoverflow.com/a/7032671/816620
Pass non-static information into a delayed callback: https://stackoverflow.com/a/8660518/816620
I know I've used closures dozens of times in the last month just here in SO answers (I'm just not sure how to quickly find more examples with search without wading through lots of posts).
And, here's a useful closure that creates a private variable:
functionslides(images) {
var slideImages = images || [];
// because of this closure, the variable slideImages is available// to the method defined in here even though the slides function// has already finished executingthis.addSlide = function(url) {
slideImages.push(url);
}
this.clearSlides = function() {
slideImages = [];
}
}
// the slideImages variable is not available out here// it is truly private inside the clsourevar slideshow = newslides(imgArray);
slideshow.addSlide("xxx.jpeg");
Solution 2:
Well, one neat thing you can do is have private variables:
functionThing() {
var x = 10;
this.getX = function () {
return x;
}
this.increment = function () {
x++;
}
}
Now, when you create a new Thing
, it will have a getX
and increment
method but no way to lower the value of x
. This value of x
will also be unique per instance of Thing
.
Crockford has a page about this pattern: http://javascript.crockford.com/private.html
Solution 3:
A basic example:
var getDay = (function () {
var days = [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday'
];
returnfunction ( n ) {
return days[ n - 1 ];
};
}());
The idea is to assign an IIFE which returns a function to a variable. After this assignment, the variable holds the function that was returned from the IIFE. Since this function was nested inside the IIFE, it has access to all its local variables and arguments, even though the IIFE itself doesn't exist anymore.
So, the whole purpose of the IIFE in the above example was to define an days
array which acts as a private variable of the getDay
function.
Solution 4:
I used closures to implement lambda expressions for a library I'm working on.
JLinx.Delegate=function() {
var validateArg=function(arg) {
if(typeof arg!=="string"&&typeof arg!=="function"&&arg!==null&&arg!==undefined) {
thrownewArgumentException("arg");
}
};
var funcBody;
functionprepBody(code,returnsResult) {
var temp=code.trimLeft().trimRight();
if(returnsResult&&temp.indexOf("return ")== -1) {temp="return "+temp;}
if(temp.substr(temp.length-1,1)!=";") {temp+=";";}
return temp;
}
functiongetDelegate(arg,defaultLambda,returnsResult) {
validateArg(arg);
if(typeof arg==="function") {return arg;}
arg=(arg===null||arg===undefined)?defaultLambda:arg;
if(arg.indexOf("=>")> -1) {
var parts=arg.split("=>");
var argList=parts[0];
funcBody=prepBody(parts[1],returnsResult);
argList=argList.trimLeft().trimRight()==""?"e":argList;
argList=(argList.indexOf(",")> -1)?argList.split(","):[argList];
switch(argList.length) {
case1:
returnnewFunction(argList[0],funcBody);
case2:
returnnewFunction(argList[0],argList[1],funcBody);
default:
thrownewInvalidOperationException("Invalid number of arguments to action delegate.");
}
}
else {
funcBody=prepBody(arg,returnsResult);
returnnewFunction("e",funcBody);
}
}
var factory=
{
actionFrom: function(arg) { returngetDelegate(arg,"e => return;",false); },
accumulatorFrom: function(arg) { returngetDelegate(arg,"e, v => return v;",true); },
comparerFrom: function(arg) { returngetDelegate(arg,"l,r=>return l<r?-1:l>r?1:0;",true); },
joinSelectorFrom: function(arg) { returngetDelegate(arg,"o, i = { return { o : o, i : i }; };",true); },
predicateFrom: function(arg) { returngetDelegate(arg,"e => return true;",true); },
selectorFrom: function(arg) { returngetDelegate(arg,"e => return e;",true); }
};
return factory;
} ();
I know this doesn't look like much, but what it allows you to do with the other methods in the library (which actually provides LINQ-to-XML) is write the following:
var exists = myXmlElement.Any("e.name == 'foo' || e.name == 'bar';');
The closure provides a factory that converts a string to a Function that is executed for each element in a Sequence object. If the argument is already a Function, it is returned directly.
That's one thing you can do with closures.
Solution 5:
It's not really that mind blowing. Languages like Java don't have closures, but you can still write good software with them.
That said, there is a lot of convenience to being able to do something like
var that = this; // that is defined outside of the function below, but is still in its// lexical scope
arry.each(function(item){
that.doSomething(item); // which means 'that' is "closed-in" to this function
});
Post a Comment for "Good Examples For Using A Closure In Javascript"