I'm using a function to lazy-load the Sizzle selector engine (used by jQuery):
var sizzle_loaded;
// load the Sizzle script
function load_sizzle(module_name) {
var script;
// load Sizzle script and set up 'onload' and 'onreadystatechange' event
// handlers to ensure that external script is loaded before dependent
// code is executed
script = document.createElement('script');
script.src = 'sizzle.min.js';
script.onload = function() {
sizzle_loaded = true;
gather_content(module_name);
};
script.onreadystatechange = function() {
if ((script.readyState === 'loaded' || script.readyState === 'complete') &&
!sizzle_loaded) {
sizzle_loaded = true;
gather_content(module_name);
}
};
// append script to the document
document.getElementsByTagName('head')[0].appendChild(script);
}
I set the onload
and onreadystatechange
event handlers, as well as the sizzle_loaded
flag to call another function (gather_content()
) as soon as Sizzle has loaded. All of this is needed to do this in a cross-browser way.
Until now, my project only had to lazy-load Sizzle at one point in the script, so I was able to just hard-code the gather_content()
function call into the load_sizzle()
function.
However, I now need to lazy-load Sizzle at two different points in the script, and call a different function either time once it's loaded. My first instinct was to modify the function to accept a callback function:
var sizzle_loaded;
// load the Sizzle script
function load_sizzle(module_name, callback) {
var script;
// load Sizzle script and set up 'onload' and 'onreadystatechange' event
// handlers to ensure that external script is loaded before dependent
// code is executed
script = document.createElement('script'开发者_StackOverflow中文版);
script.src = 'sizzle.min.js';
script.onload = function() {
sizzle_loaded = true;
callback(module_name);
};
script.onreadystatechange = function() {
if ((script.readyState === 'loaded' || script.readyState === 'complete') &&
!sizzle_loaded) {
sizzle_loaded = true;
callback(module_name);
}
};
// append script to the document
document.getElementsByTagName('head')[0].appendChild(script);
}
Then, I could just call it like this:
load_sizzle(module_name, gather_content);
However, the other callback function that I need to use takes more parameters than gather_content()
does.
How can I modify my function so that I can specify a variable number of parameters, to be passed with the callback function? Or, am I going about this the wrong way?
Ultimately, I just want to load Sizzle, then call any function that I need to (with any arguments that it needs) once it's done loading.
Thanks for any help!
The general idea here is to create a closure or lambda. In a way, you can consider them as a function that's pre-loaded with parameters that's ready to be called. This is also sometimes called a delegate.
load_sizzle( module_name, function()
{
gather_content();
});
Then, for your other case
load_sizzle( module_name, function()
{
some_other_function( param1, param2 );
});
More reading on closures.
You can use arguments array to get all arguments that were passed into the function.
function example() {
for( var i = 0; i < arguments.length; i++ ) {
alert('argument ' + i + ' ' + arguments[i]);
}
}
example('any', 'number', 'of', 'arguments);
You can use the apply method on the callback:
function load_sizzle(module_name, callback,args) {
var script, args=args || []; //Be sure that an array is passed
// load Sizzle script and set up 'onload' and 'onreadystatechange' event
// handlers to ensure that external script is loaded before dependent
// code is executed
script = document.createElement('script');
script.src = 'sizzle.min.js';
script.onload = function() {
sizzle_loaded = true;
callback.apply(window,[module_name].concat(args)); //Add the module_name as first argument and then every other argument specified by the user
};
script.onreadystatechange = function() {
if ((script.readyState === 'loaded' || script.readyState === 'complete') &&
!sizzle_loaded) {
sizzle_loaded = true;
callback(module_name);
}
};
// append script to the document
document.getElementsByTagName('head')[0].appendChild(script);
}
Then as third argument of load_sizzle you can pass an array of extra arguments for the function.
You can also improve the code with this:
function load_sizzle(module_name, callback,args,bind) {
var script, args=args || [],bind=bind || window;
// load Sizzle script and set up 'onload' and 'onreadystatechange' event
// handlers to ensure that external script is loaded before dependent
// code is executed
script = document.createElement('script');
script.src = 'sizzle.min.js';
script.onload = function() {
sizzle_loaded = true;
callback.apply(bind,[module_name].concat(args)); //Add the module_name as first argument and then every other argument specified by the user
};
script.onreadystatechange = function() {
if ((script.readyState === 'loaded' || script.readyState === 'complete') &&
!sizzle_loaded) {
sizzle_loaded = true;
callback(module_name);
}
};
// append script to the document
document.getElementsByTagName('head')[0].appendChild(script);
}
In this way the argument number 4 (if specified) can be an object that will be the "this" inside the callback that you pass.
精彩评论