JS: variable inheritance in anonymous functions - scope
Long story short:
var o="before";
x = function() //this needs to be an anonymous function
{
alert(o); //the variable "o" is from the parent scope
};
o="after"; //this chages "o" in the anonymous function
x();
//this results in in alert("after");
//which is not the way i want/need it
in reality my code is somewhat more complex.
My script iterates through many html objects and adds an event listener each element.
I do this by declaring an anonymous function for each element and call another function with an ID as argument. that ID is represented by the "o"-variable in this ex开发者_开发知识库ample.
After some thinking I understand why it is the way it is, but is there a way to get js to evaluate o as i declare the anonymous function without dealing with the id attribute and fetching my ID from there?
My full source code is here: http://pastebin.com/GMieerdw
The anonymous function is on line 303.
You need to create a closure of your variable o
. You can do this by assigning a function that accepts a value returns a function which uses that value. Your example can be modified like this to get the desired effect:
var o="before";
x = function(inner) {
return function()
{
alert(inner);
}
} (o); //here, the anonymous function is called, which will return another function which uses o
o="after";
x();//prints "before"
For a more detailed description, see the MDC article, which has a section about using closures with loops.
This same technique can be applied in your loop. Something like this is what you would want to do:
var fn = function(x, y) {
return function() {
rr_download_start(x, y);
}
} (i, this);
link.addEventListener('click', fn ,false);
You can try using a self-invoking function like this:
var o = 0;
for(var i=0;i<elements.length;i++){
(function(obj,variable){
obj.onclick = function(){
alert(variable);
}
})(elements[i],o);
o++;
}
That should alert "o" at whatever value it was during the loop, instead of alerting the final value of "o".
I hope this helps in some way.
One way is to create a currying function:
function curry(fun, arg) {
return function() {
return fun(arg);
};
};
// start loop
var o="before";
x = curry(function(o) {
alert(o);
}, o);
o="after";
x(); // "before"
Another way is to use an external data source - since this
will depend on where the function was called, you can store the value in the DOM node to which you bind the handler. This way you can use a single function instead lots of anonymous functions. This technique has a few caveats (circular references can cause memory leaks in IE6), but frameworks can have a nice clean wrapper for it. E. g. in jQuery you can write:
function doStuff() {
alert($(this).data('o'));
}
// start loop
var o="before";
someDomElement.data('o', 'before');
someDomElement.bind('someEvent', doStuff);
o="after";
someDomElement.trigger('someEvent'); // "before"
精彩评论