开发者

How do I pass a variable number of parameters along with a callback function?

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜