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

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

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

Любой берущий?

9 ответов

Решение

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

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

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

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

так

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

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

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

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

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

Посмотрите на использование делегирования событий вместо этого. Вот где вы на самом деле смотрите событие в контейнере, который не исчезает, а затем используете 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, Closure или любые другие, должны предлагать функции делегирования событий, чтобы сгладить различия между браузерами и аккуратно обрабатывать крайние случаи. 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 defineAndRun(name, func) {
    window[name] = func;
    func();
}

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

Еще проще с 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"

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

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

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

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

Для своего приложения я пошел по самому простому пути. Мне просто нужно немедленно запустить функцию при загрузке страницы и снова использовать ее также в нескольких других разделах кода.

      function doMyFunctionNow(){
    //for example change the color of a div
}

var flag = true;
if(flag){
    doMyFunctionNow();
}
Другие вопросы по тегам