A while back I posted about a JavaScript issue that I’ve run into quite commonly with callbacks and in working around DOM elements that don’t want to update properly until UI control returns to them. In those scenarios it’s essential to delay execution of a function call. You can then use window.setTimeout() to delay the execution easily enough;
Where this gets tricky is if you need to pass parameters and the question is how do you pass parameters to these calls. I’ve been using strings because that’s the only way I could figure out how to pass the parameters in the proper context. So for example to call a function that delays might look like this:
window.setTimeout("Fadeout('" + ControlId + "'," + HideOnZero.toString() + "," +
Step.toString() + "," + Percent.toString() + "," +
UseVisibility.toString() +")",30);
Where the various values passed as literals here are parameters of function. The idea here is that a Fadeout function calls itself with updated percentage parameters until it’s gone.
As several people pointed out in the original post it's not really a good idea to use strings for callbacks like this. It works but it gets messy real fast to write out those parameter strings, especially if you’re trying to do this in ASP.NET server code for embedding into the ClientScript object. The string delimiters get in the way real fast and it’s easy to make a typo in this sort of code.
So today an anonymous post replied on the original thread to look into function.apply and function.call. These functions essentially let you capture the current call context by passing an object reference that maintains the call context.
It’s easier to see in the resulting code:
window.setTimeout( function() { Fadeout.call(this, ControlId,HideOnZero,
Step,Percent, UseVisibility); },30);
setTimeout allows a function pointer, so this code creates a new function and uses Fadeout.call(this, ParmList). The this pointer in this case is a the current function and so this is the context that these parameter values use when the function is actually called.
It works and surely makes life a lot easier when using indirect calls to functions.
Function.apply is similar to call, except that it accepts an array of arguments as opposed to a fixed parameter list. This is actually easier as you can in most cases just pass the generic arguments array that JavaScript exposes:
window.setTimeout( function() { Fadeout.call(this, arguments); },30);
or:
var Parms = new Array(ControlId,HideOnZero,Step,Percent,UseVisibility);
window.setTimeout( function() { Fadeout.call(this, Parms); },30);
window.setTimeout( function() { Fadeout.call(this, ["Hello",10] ); },30);
I’m not sure I really ‘understand’ how the context is kept in these calls and whether this results in some possible memory issues. But in some quick testing with several browsers it seems to work fine without any visible side-effects.
Other Posts you might also like