When to use a self-executing function

I understand that the main difference between

(function(){
  // code...
})();

and

// code...

is the scope of the variables, but are there times when it is better to use (or not to use) a self-executing function?

For example, I have a simple show/hide script on 3 of my sites.

(function() {
  const x = document.getElementById("showHide"),
    y = document.getElementById("btnShow");
  y.style.display = "inline-block";
  x.style.display = "none";
  y.addEventListener("click", function() {
    if (x.style.display === "none") {
      x.style.display = "inline-block";
      y.innerHTML = "Less...";
    } else {
      x.style.display = "none";
      y.innerHTML = "More...";
    }
  });
})();

It works fine on 2 of the sites, but on the 3rd I found it would only work if I removed the top and tail, ie the (function() {})();

Well, for one it can be to avoid cluttering the global variable space with variables. things wrapped inside an anonymous self-executing function are variable-scoped to the function, meaning your x and y dont exist once the function ends.

Secondly its often helpful for scripts that want to be, say, Wordpress compatible with things like jQuery. tweak the code slightly:

(function() {
  const x = $("#showHide"),
    y = $("#btnShow");
  y.style.display = "inline-block";
  x.style.display = "none";
  y.addEventListener("click", function() {
    if (x.style.display === "none") {
      x.style.display = "inline-block";
      y.innerHTML = "Less...";
    } else {
      x.style.display = "none";
      y.innerHTML = "More...";
    }
  });
})();

(I haven’t done a full replacement there, but you get the point.)
If the script is being loaded in something like Wordpress, this will fail. But:

(function($) {
  const x = $("#showHide"),
    y = $("#btnShow");
  y.style.display = "inline-block";
  x.style.display = "none";
  y.addEventListener("click", function() {
    if (x.style.display === "none") {
      x.style.display = "inline-block";
      y.innerHTML = "Less...";
    } else {
      x.style.display = "none";
      y.innerHTML = "More...";
    }
  });
})(jQuery);

will work. minimal code change (adding a parameter), and suddenly the code all works. “Dependency Injection”, this is sometimes called.

2 Likes

What is happening on the third site that causes the problem?

1 Like

Well, being something of a prune, I had omitted to check for errors before now. :blush: Now I do so, I see it is telling me

Uncaught TypeError: document.addEventListener(...) is not a function

Can we take a look at the page so that we may investigate what is going on?

1 Like

Well, I spotted a missing semi-colon on the line before the anonymous function. Adding that fixed the problem.

I thought semi-colons were optional in JS - I know one developer who hardly uses them at all.

1 Like

I think what I’m hearing is that it’s “quite a good thing” to wrap up sections of code as anonymous self-executing functions?

They’re optional, until the line that follows them could be part of the previous line syntactically.
Most commonly - when a line begins with a (, because it could be interpreted to be the parameter definition of a function on the previous line:

The ECMA specification gives this as an example:

a = b + c
(d + e).print()

Javascript handles this as though you had written:
a = b + c(d + e).print() (making the d+e a functional parameter of c)

2 Likes