55

A long time ago, I saw someone encapsulate their entire JavaScript block with code something like the code below:

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

Questions:

  1. Is the code above correct?
  2. What benefit is there to encapsulating the entire JavaScript block like denoted above?
Cœur
  • 37,241
  • 25
  • 195
  • 267
nickb
  • 9,140
  • 11
  • 39
  • 48

3 Answers3

91

Yes, that's correct. It's called a self invoking anonymous function expression.

JavaScript variables have either function scope, or global scope. There is no block scope. Enclosing your code in a self invoking function like the one in your example creates a temporary local scope for single-use, immediately-run code, without polluting the global namespace.

Consider the following:

<html>
<body>
...
<script>
   (function() { 
      var x = '';

      function myFunction () {
         alert('Hello: ' + x);
      }

      x = 'Bob';
      myFunction();

      alert(typeof x);            // string
      alert(typeof myFunction);   // function
   })();

   alert(typeof x);               // undefined
   alert(typeof myFunction);      // undefined
</script>
<script src="other-javascript.js"></script>
</body>
</html>

Whatever you declare in that self invoking function is held in a separate scope. The variable x and the function myFunction() cannot be accessed from anywhere else. The code in other-javascript.js won't see them, for example, and it would be free to declare another function myFunction() without conflicts.

Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • 1
    So is "block" scope like a private variable? – nickb Aug 30 '10 at 00:10
  • @user434493: Unlike C, C++, Java, and other languages, the variable `y` in `if (x > 5) { var y = 0; }` can be accessed from outside the `if` block... That would have been block scope, but JavaScript variables are stored in a function environment, and are not affected by other `{ }` blocks. Let me update my answer with an example... – Daniel Vassallo Aug 30 '10 at 00:20
  • 3
    How would you set a variable from outside of the encapsulation to an object from within the encapsulation? – user3015682 May 20 '15 at 19:32
  • The preferred term seems to be now ["immediately invoked function expression" (IIFE)](https://en.wikipedia.org/wiki/Immediately_invoked_function_expression). Probably because it's not invoking itself. (See also [MDN](https://developer.mozilla.org/en-US/docs/Glossary/IIFE?retiredLocale=de).) – kca Jun 28 '23 at 12:12
39

Also addition to the @Daniel's answer, passing this to the function is a common pattern to have a reference to the global object, for example:

(function(window){

})(this);

In browser scripting the global object has a property named window which refers to the global object itself, in other environments there is no window property.

Also, another thing that can be done is to specify an argument named undefined, because the undefined property is not described on the ECMAScript 3rd. Edition Standard (there is no guarantee that exist or not), and in some implementations the property is mutable, for example:

(function(window, undefined){

})(this);

In the above example, we have two local identifiers (which are a bit faster to resolve), window and undefined, only the first one is passed (this, which always refers to the global object in Global code (code that is outside of any function)), and the second, will contain the primitive undefined value, because we are not passing any value to it.

That pattern is used by some libraries like jQuery.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
0

Just for the record, ECMA TC39 had proposed a private syntax. According to the proposal, in order to make a javascript class field private you need to prefix it with a hash '#'. This is to provide some sort of runtime encapsulation.

Example:

class B {
  #hidden = 0;
  m() {
    return this.#hidden;
  }
}

Chrome supports this since Chrome v74. If this private-syntax becomes a standart we will be able to benefit from runtime encapsulation in javascript and assumingly in typescript since it's transpilation will be updated that way.

talhature
  • 2,246
  • 1
  • 14
  • 28