2

I was looking at this piece of code in an exercise which returns another function within a function:

var dayName = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return function(number) {
    return names[number];
  };
}();
console.log(dayName(3));
// → Wednesday

However, even if I don't return another function, this alternative code works too:

var dayName = function(number) {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return names[number];
};
console.log(dayName(3));
// → Wednesday

Can someone please explain what is the point of the 1st method? And if there is any difference between using the 1st and 2nd method?

Thanks!

Rachel
  • 111
  • 4
  • possible duplicate of [How do JavaScript closures work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – cwharris Aug 21 '14 at 05:17

5 Answers5

1

The second method recreates the names array every time - just to index into it and throw the array itself and most of the strings therein there away.

The first method, called a closure, creates names only once (when the outer function is called initially). The inner function retains a reference to all of its enclosing scopes and thus has access to names.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
1

The first option executes the outer function when the code first initializes (by virtue of the () at the end of the definition) and assigns the inner function to the variable dayName. This gets the same function logic into the dayName symbol, but the first option allows the array names to live inside a closure. This closure offers the following benefits:

  1. The array is only evaluated once at startup time rather than every time the function is called (which happens in your second option).
  2. The array name is in a private namespace and doesn't add anything to the global namespace (which would happen if you moved the array outside the function so that it was only evaluated once).
  3. The array can be only accessed or modified by the function and is not accessible from outside the function and thus is more tamperproof.
  4. The array can be modified in a persistent fashion (from within the function) which will last from one function call to the next. This isn't being done in this case, but can be an advantage of this design pattern. You can also add other variables to the closure that will similarly persist from one function call to the next. This is not possible in your second option unless you create global variables outside the function.

So returning the function gets you the best of both worlds. The only drawback to the first option is that the function name is not hoisted to the top of the JS file like static function declarations are so it's not available until this code executes. This is normally not a significant issue, but it does require you to be slightly more careful with the sequence of code definitions vs. usage in startup code.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

The first version only defines names once (and doesn't pollute the global namespace with it). The second version will define names each time dayName is called.

Amadan
  • 191,408
  • 23
  • 240
  • 301
0

First option

var dayName = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return function(number) {
    return names[number];
  };
}();//<-- anonymous function already invoked, so now dayName has the reference of inner function along with the array created.
console.log(dayName);//<-- prints, function (number) { return names[number]; }
console.log(dayName(1));//<-- prints, Monday

Anonymous function not invoked

var dayName = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return function(number) {
    return names[number];
  };
};//<-- anonymous function not invoked
console.log(dayName()(1));//<-- prints, Monday

Second option

var dayName = function(number) {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return names[number];//<-- returns the array element for given parameter index
};//<-- not invoked
console.log(dayName(1));//<-- prints, Monday
0

This is how javascript achieves data hiding and encapsulation.The names variable in the first snippet becomes a variable , that can only be accessed by the privileged function that you are returning.

  return function(number) { // this is the privileged function
    return names[number];   
  };

There is no way you can directly access the names without the help of your privileged function.This concept is called closures in javascript

Prabhu Murthy
  • 9,031
  • 5
  • 29
  • 36