Могу ли я назвать функцию JavaScript и выполнить ее немедленно? - PullRequest
73 голосов
/ 19 июня 2011

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

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

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

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

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

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

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

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

Любые получатели

Ответы [ 8 ]

104 голосов
/ 19 июня 2011

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

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

Существует два способа определения функции в JavaScript,Объявление функции:

function foo(){ ... }

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

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

... etc

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

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

, но это не так:

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

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

11 голосов
/ 08 мая 2014

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

var func = (function f(a) { console.log(a); return f; })('Blammo')
5 голосов
/ 19 июня 2011

В этом нет ничего плохого (или есть?), Но можно ли его немного сгладить?

Взгляните на использование делегирования событий.Вот где вы фактически наблюдаете событие в контейнере, который не исчезает, а затем используете 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 , Prototype, YUI , Закрытие или любой из нескольких других должны предлагать функции делегирования событий для сглаживания различий в браузере и аккуратной обработки краевых случаев.jQuery, безусловно, поддерживает обе функции: live и delegate, которые позволяют указывать обработчики с использованием полного набора селекторов CSS3 (а затем и некоторых).

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

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

Live copy

4 голосов
/ 19 июня 2011

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

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

так

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

работает. Ура!

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

var addEventsAndStuff = (
 function(){
  var addeventsandstuff =  function(){
    alert('oele');
  };
  addeventsandstuff();
  return addeventsandstuff;
 }()
);
4 голосов
/ 19 июня 2011

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

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

defineAndRun('addEventsAndStuff', function() {
    alert('oele');
});
1 голос
/ 23 октября 2018

Еще проще с ES6:

var result = ((a, b) => `${a} ${b}`)('Hello','World')
// result = "Hello World"
var result2 = (a => a*2)(5)
// result2 = 10
var result3 = (concat_two = (a, b) => `${a} ${b}`)('Hello','World')
// result3 = "Hello World"
concat_two("My name", "is Foo")
// "My name is Foo"
0 голосов
/ 19 июня 2011

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

// 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();
0 голосов
/ 19 июня 2011

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

var addEventsAndStuff = (function(){
    var func = function(){
        alert('ole!');
    };
    func();
    return func;
})();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...