1
var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
//Execute

digit_name(0)

VERSUS

 var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();

then execute it like this:

digit_name(2)

I know these are both closures, but I also think that there are some fundamental differences between the way the two are setup. Can someone point out how different are these two setups (especially considering both get the same job done)? Attaching a global variable to the 'window' vs nesting functions to emulate private variable is one I can think of..

EDIT - I am now confused whether to think of the first setup as a closure or not...Using chrome, I investigated the two setups..

var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();
undefined
console.dir(digit_name)
function anonymous(n)
 arguments: null
 caller: null
 length: 1
 name: ""prototype: Object
 __proto__: function()
 <function scope>
     Closure names: Array[9]
     With Block: CommandLineAPI
     Global: Window

However for the first function in chrome,

var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
undefined
console.dir(digit_name)
function digit_name(n)
arguments: null
caller: null
length: 1
name: ""
prototype: digit_name
__proto__: function()
<function scope>
     With Block: CommandLineAPI
     Global: Window

You can see that Chrome explicitly indicates the existence of closure for the first setup, but not for the second setup..

Athapali
  • 1,091
  • 4
  • 25
  • 48
  • 2
    only the second is a closure – Nina Scholz Jan 05 '16 at 15:52
  • 3
    @NinaScholz: If a closure is defined as a function having a permanent reference to its enclosing variable scope, then every function in JS is a closure, whether or not it is taken advantage of. –  Jan 05 '16 at 15:56
  • 1
    @SariksaThapa: You've described the primary difference in your question. –  Jan 05 '16 at 15:57
  • @squint, in the first case there is no enclosing function. `names` is a global variable. – Nina Scholz Jan 05 '16 at 16:06
  • @NinaScholz can you explain to me why the first setup doesn't look like a closure to you? How is the function accessing the 'names' array elements then?? You can clearly see that 'names' is not a local variable for that function... – Athapali Jan 05 '16 at 16:06
  • 1
    @NinaScholz: The function in the first example is still nevertheless bound to its enclosing execution environment, which is the global environment. The global environment is the only one that isn't bound to anything. –  Jan 05 '16 at 16:09
  • @squint am I correct to say "if there are no elements existing outside the scope of the function utilized within the function, it is not effectively a closure because nothing is enclosed. " e.g. `var name = "John"; function(){alert ("Hello John!"); }` is not a closure – Athapali Jan 05 '16 at 16:23
  • 1
    @SariksaThapa: First, technically it doesn't need to be a closure to access outer variables. It only needs to be lexically scoped. However, the fact that it's not merely lexically scoped, but also has a permanent binding to its enclosing scope makes it a closure. As to nothing being enclosed, the basic structure of the variable scope is the same. It is still bound to its outer environment. ***However***, that doesn't preclude JS engines from optimizing away that binding when not necessary. I'm sure all modern engines do this. That said, it is still conceptually a closure. *[more to come]* –  Jan 05 '16 at 16:26
  • 1
    @SariksaThapa Any function is closure. – Vidul Jan 05 '16 at 16:27
  • @SariksaThapa: Imagine you have some non-global variable in your code that never gets used. The JS engine could certainly optimize it away. Would we say that it therefore isn't a variable? No. But there's another catch. Engines can't always optimize these things away. What if an enclosed function had `alert(eval(document.getElementById("foo").value));`. If the `.value` provides the name of some variable, it can still access the variable. This could only happen if there's a closure, which must exist even though no variable name was actually referenced in code. –  Jan 05 '16 at 16:30
  • Finally, remember that a function can also be moved to a different `window` environment. This means that even global functions need to create a closure in order to keep referencing their original global environment. So as @NinaScholz suggested it may seem as though a closure isn't needed, but it actually still is. –  Jan 05 '16 at 16:34
  • @squint see my updated question.. could that just be chrome browser's interpretation? by the way, you should probably compile all your comments and turn that into an answer!! Great comments.. – Athapali Jan 05 '16 at 16:39
  • 2
    Don't rely too much on console output to interpret the meaning of a language. The console only displays what its developers have decided it should display. They probably just left it off because it's already represented by the `Global`. I've gone pretty far beyond your question but you have touched on the main difference between the two original code examples. Accessibility to the `names` is the only practical difference. –  Jan 05 '16 at 16:44

2 Answers2

1

I know these are both closures

Correct.

but I also think that there are some fundamental differences between the way the two are setup.

Wrong.

This:

var names = ["zero", "one", "two"]; // outer scope variable
var digit_name = function (n) {                        // closure -------+
    return names[n]; // outer scope variable reference                   |
}                                                      // ---------------+

and this

var digit_name = (function() {                        // closure --------+
    var names = ["zero", "one", "two"]; // outer scope variable          |
    return function(n) {                                 // closure ---+ |
        return names[n];  // outer scope variable reference            | |
    }                                                    // -----------+ |
})();                                                 // ----------------+

is exactly the same thing, functionally, the only real difference being the number of closures.

Every function in JavaScript creates a closure, it's as simple as that.

Don't let the different ways of setting up closures (function statements, function expressions or immediately-executed function expressions) confuse you, ultimately it all amounts to the same thing.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • but when every function is a closure, why is the term closure needed and taken? – Nina Scholz Jan 05 '16 at 18:04
  • 1
    Because "closure" is a *concept* about scope handling. It defefines semantics, that just happen to coincide with the Javascript function keyword. – Tomalak Jan 05 '16 at 20:43
0

First let us understand what closure is in simple words.

Closure is a inner function which has access to variables of the outer function (wrapper function).

Now the closure function has magical power of accessing variables with three different scopes.

  1. Variables of it's local scope.
  2. Variables of it's outer function's scope.
  3. Variables of global scope.

Now if we look at your both the scenarios you described.

First :

var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
//Execute

digit_name(0)

here the variable names and digit_name has a global scope as it is declared directly, in browser's case which is window ( i.e you can access it using window.names). Now the function stored in digit_name is clearly accessing a global variable.

So here closure no where comes in picture. (It's a simple example of function accessing a global variable.

Second :

 var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();

Here digit_name has a global scope and the function stored in digit_name is a closure, because it is wrapped up in an outer function (anonymous) which is immediately called after declaration. Now the variable names has a local scope because it is declared inside a function and the closure function is accessing a local variable of this function because it falls under the scope of outer (wrapper) function.

This is an example of closure function.

I hope this helps you to understand closure.

For more information you can take a look at more examples here

and for understanding scope you can refer this answer

Community
  • 1
  • 1
Ravi Rupeliya
  • 621
  • 4
  • 16