Can I name a JavaScript function and execute it immediately?

JavascriptFunction

Javascript Problem Overview


I have quite a few of these:

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

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

Re-adding the events is necessary because the DOM has changed, so previously attached events are gone. Since they have to be attached initially as well (duh), they're in a nice function to be DRY.

There's nothing wrong with this set up (or is there?), but can I smooth it a little bit? I'd like to create the addEventsAndStuff() function and immediately call it, so it doesn't look so amateuristic.

Both following respond with a syntax error:

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

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

Any takers?

Javascript Solutions


Solution 1 - Javascript

There's nothing wrong with the example you posted in your question.. The other way of doing it may look odd, but:

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

There are two ways to define a function in JavaScript. A function declaration:

function foo(){ ... }

and a function expression, which is any way of defining a function other than the above:

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

...etc

function expressions can be named, but their name is not propagated to the containing scope. Meaning this code is valid:

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

but this isn't:

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

So in order to name your function and immediately call it, you need to define a local variable, assign your function to it as an expression, then call it.

Solution 2 - Javascript

There is a good shorthand to this (not needing to declare any variables bar the assignment of the function):

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

Solution 3 - Javascript

> There's nothing wrong with this set up (or is there?), but can I smooth it a little bit?

Look at using event delegation instead. That's where you actually watch for the event on a container that doesn't go away, and then use event.target (or event.srcElement on IE) to figure out where the event actually occurred and handle it correctly.

That way, you only attach the handler(s) once, and they just keep working even when you swap out content.

Here's an example of event delegation without using any helper libs:

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

Live example

Note how if you click the messages that get dynamically added to the page, your click gets registered and handled even though there's no code to hook events on the new paragraphs being added. Also note how your handlers are just entries in a map, and you have one handler on the document.body that does all the dispatching. Now, you probably root this in something more targeted than document.body, but you get the idea. Also, in the above we're basically dispatching by id, but you can do matching as complex or simple as you like.

Modern JavaScript libraries like jQuery, Prototype, YUI, Closure, or any of several others should offer event delegation features to smooth over browser differences and handle edge cases cleanly. jQuery certainly does, with both its live and delegate functions, which allow you to specify handlers using a full range of CSS3 selectors (and then some).

For example, here's the equivalent code using jQuery (except I'm sure jQuery handles edge cases the off-the-cuff raw version above doesn't):

(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

Solution 4 - Javascript

Your code contains a typo:

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

so

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

works. Cheers!

[edit] based on comment: and this should run and return the function in one go:

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

Solution 5 - Javascript

You might want to create a helper function like this:

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

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

Solution 6 - Javascript

Even simpler with 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"

Solution 7 - Javascript

If you want to create a function and execute immediately -

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

Solution 8 - Javascript

Try to do like that:

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

Solution 9 - Javascript

For my application I went for the easiest way. I just need to fire a function immediately when the page load and use it again also in several other code sections.

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

var flag = true;
if(flag){
    doMyFunctionNow();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRudieView Question on Stackoverflow
Solution 1 - JavascriptNoneView Answer on Stackoverflow
Solution 2 - JavascriptJames GorrieView Answer on Stackoverflow
Solution 3 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 4 - JavascriptKooiIncView Answer on Stackoverflow
Solution 5 - JavascriptpimvdbView Answer on Stackoverflow
Solution 6 - JavascriptAlbertoView Answer on Stackoverflow
Solution 7 - JavascriptPraveen LoboView Answer on Stackoverflow
Solution 8 - JavascriptAlexander RuliovView Answer on Stackoverflow
Solution 9 - JavascriptPietroView Answer on Stackoverflow