Могу ли я назвать функцию JavaScript и выполнить ее немедленно?


у меня их довольно много:

function addEventsAndStuff() {
  // bla bla
}
addEventsAndStuff();

function sendStuffToServer() {
  // send stuff
  // get HTML in response
  // replace DOM
  // add events:
  addEventsAndStuff();
}

повторное добавление событий необходимо, потому что DOM изменился, поэтому ранее прикрепленные события исчезли. Поскольку они также должны быть прикреплены изначально (duh), они находятся в хорошей функции, чтобы быть сухими.

нет ничего плохого в этом (или есть?), но могу ли я немного сгладить его? Я хотел бы создать addEventsAndStuff() функция и сразу же вызвать его, так что это не выглядит так дилетантски.

как следующий ответ с синтаксической ошибкой:

function addEventsAndStuff() {
  alert('oele');
}();

(function addEventsAndStuff() {
  alert('oele');
})();

кто-нибудь?

7 65

7 ответов:

нет ничего плохого в Примере, который вы опубликовали в своем вопросе.. Другой способ сделать это может показаться странным, но:

var addEventsAndStuff;
(addEventsAndStuff = function(){
    // add events, and ... stuff
})();

есть два способа определить функцию в JavaScript. Объявление функции:

function foo(){ ... }

и выражение функции, которое является любой способ определения функции, отличной от приведенной выше:

var foo = function(){};
(function(){})();
var foo = {bar : function(){}};

...и т. д.

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

(function foo(){
   foo(); // recursion for some reason
}());

но это не так:

(function foo(){
    ...
}());
foo(); // foo does not exist

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

есть хорошая стенография к этому (не нужно объявлять какие-либо переменные бар назначение функции):

var func = (function f(a) { console.log(a); return f; })('Blammo')

нет ничего плохого в этом (или есть?), но могу ли я немного сгладить его?

посмотрите на использование делегирования событий вместо этого. Вот где вы на самом деле наблюдаете за событием на контейнере, который не уходи, а потом используй event.target (или event.srcElement на IE), чтобы выяснить, где на самом деле произошло событие и обрабатывать его правильно.

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

вот пример делегирования событий без использования вспомогательных библиотек:

(function() {
  var handlers = {};

  if (document.body.addEventListener) {
    document.body.addEventListener('click', handleBodyClick, false);
  }
  else if (document.body.attachEvent) {
    document.body.attachEvent('onclick', handleBodyClick);
  }
  else {
    document.body.onclick = handleBodyClick;
  }

  handlers.button1 = function() {
    display("Button One clicked");
    return false;
  };
  handlers.button2 = function() {
    display("Button Two clicked");
    return false;
  };
  handlers.outerDiv = function() {
    display("Outer div clicked");
    return false;
  };
  handlers.innerDiv1 = function() {
    display("Inner div 1 clicked, not cancelling event");
  };
  handlers.innerDiv2 = function() {
    display("Inner div 2 clicked, cancelling event");
    return false;
  };

  function handleBodyClick(event) {
    var target, handler;

    event = event || window.event;
    target = event.target || event.srcElement;

    while (target && target !== this) {
      if (target.id) {
        handler = handlers[target.id];
        if (handler) {
          if (handler.call(this, event) === false) {
            if (event.preventDefault) {
              event.preventDefault();
            }
            return false;
          }
        }
      }
      else if (target.tagName === "P") {
        display("You clicked the message '" + target.innerHTML + "'");
      }
      target = target.parentNode;
    }
  }

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
  }

})();

видео

обратите внимание, как при нажатии на сообщения, которые динамически добавляются на страницу, ваш клик регистрируется и обрабатывается, даже если нет кода для подключения событий к новым добавляемым абзацам. Также обратите внимание, что ваши обработчики-это просто записи на карте, и у вас есть один обработчик на document.body это делает всю диспетчеризацию. Теперь вы, вероятно, укорените это в чем-то более целенаправленном, чем document.body, но вы получаете идею. Кроме того, в приведенном выше мы в основном отправляем по id, но вы можете сделать сопоставление столь же сложным или простым, как вам нравится.

современные библиотеки JavaScript, такие как jQuery,прототип,Юи,закрытие или любой из нескольких других должны предлагать функции делегирования событий для сглаживания различия браузера и обрабатывать крайние случаи чисто. jQuery, конечно, делает, с обоими его live и delegate функции, которые позволяют указать обработчики, используя полный спектр CSS3 селекторов (а затем некоторые).

например, вот эквивалентный код, использующий jQuery (за исключением того, что я уверен, что jQuery обрабатывает крайние случаи, когда исходная версия вне манжеты выше этого не делает):

(function($) {

  $("#button1").live('click', function() {
    display("Button One clicked");
    return false;
  });
  $("#button2").live('click', function() {
    display("Button Two clicked");
    return false;
  });
  $("#outerDiv").live('click', function() {
    display("Outer div clicked");
    return false;
  });
  $("#innerDiv1").live('click', function() {
    display("Inner div 1 clicked, not cancelling event");
  });
  $("#innerDiv2").live('click', function() {
    display("Inner div 2 clicked, cancelling event");
    return false;
  });
  $("p").live('click', function() {
    display("You clicked the message '" + this.innerHTML + "'");
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

})(jQuery);

скопировать видео

ваш код содержит опечатку:

(function addEventsAndStuff() {
  alert('oele');
)/*typo here, should be }*/)();

так

(function addEventsAndStuff() {
  alert('oele');
 })();

строительство. Ура!

[edit] на основе комментария: и это должно работать и возвращать функцию за один раз:

var addEventsAndStuff = (
 function(){
  var addeventsandstuff =  function(){
    alert('oele');
  };
  addeventsandstuff();
  return addeventsandstuff;
 }()
);

вы можете создать вспомогательную функцию, как это:

function defineAndRun(name, func) {
    window[name] = func;
    func();
}

defineAndRun('addEventsAndStuff', function() {
    alert('oele');
});

Если вы хотите создать функцию и выполнить ее немедленно -

// this will create as well as execute the function a()
(a=function a() {alert("test");})();

// this will execute the function a() i.e. alert("test")
a();

попробуйте сделать так:

var addEventsAndStuff = (function(){
    var func = function(){
        alert('ole!');
    };
    func();
    return func;
})();