Как передать переменное количество параметров вместе с функцией обратного вызова? - PullRequest
2 голосов
/ 27 мая 2010

Я использую функцию для отложенной загрузки механизма выбора Sizzle (используется 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);

}

Я установил обработчики событий onload и onreadystatechange, а также флаг sizzle_loaded для вызова другой функции (gather_content()), как только Sizzle загрузится. Все это необходимо для кросс-браузерной работы.

До сих пор моему проекту приходилось только медленно загружать Sizzle в одном месте сценария, поэтому я мог просто жестко закодировать вызов функции gather_content() в функцию load_sizzle().

Однако теперь мне нужно лениво загрузить Sizzle в двух разных точках скрипта и вызывать разные функции в любое время после загрузки. Моим первым инстинктом было модифицировать функцию, чтобы она принимала функцию обратного вызова:

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');
  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);

}

Тогда я мог бы просто назвать это так:

load_sizzle(module_name, gather_content);

Однако другая функция обратного вызова, которую мне нужно использовать, принимает больше параметров, чем gather_content().

Как я могу изменить свою функцию, чтобы я мог указать переменное число параметров, которые будут переданы с функцией обратного вызова? Или я поступаю неправильно?

В конечном счете, я просто хочу загрузить Sizzle, а затем вызвать любую нужную мне функцию (с любыми необходимыми аргументами), как только загрузка будет завершена.

Спасибо за любую помощь!

Ответы [ 3 ]

3 голосов
/ 27 мая 2010

Общая идея здесь - создать замыкание или лямбду. В некотором смысле вы можете рассматривать их как функцию, которая предварительно загружена с параметрами, которые готовы к вызову. Это также иногда называют делегатом.

load_sizzle( module_name, function()
{
  gather_content();
});

Тогда, для вашего другого случая

load_sizzle( module_name, function()
{
  some_other_function( param1, param2 );
});

Подробнее о замыканиях .

2 голосов
/ 27 мая 2010

Вы можете использовать массив arguments, чтобы получить все аргументы, переданные в функцию.

function example() {
for( var i = 0; i < arguments.length; i++ ) {
    alert('argument ' + i + ' ' + arguments[i]);
}
}

example('any', 'number', 'of', 'arguments);
2 голосов
/ 27 мая 2010

Вы можете использовать метод apply для обратного вызова:

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);

}

Тогда в качестве третьего аргумента load_sizzle вы можете передать массив дополнительных аргументов для функции.

Вы также можете улучшить код с помощью этого:

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);

}

Таким образом, аргумент номер 4 (если указан) может быть объектом, который будет «this» внутри передаваемого вами обратного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...