2

This code appears in a very popular JS tutorial:

const sum = (function() {
  "use strict";
  return function sum(...args) {
    return args.reduce((a, b) => a + b, 0);
  };
})();
console.log(sum(1, 2, 3)); // 6
  1. I am trying to make sense of the reason they return a function from a function (explanation is not provided there, unfortunately). It would be simpler and straightforward if the outer function is declared with parameters, perform the calculation, and then simply return the value. Why would there be a necessity (in this case; seems like an answer to the general case can be found here) to express a function this way?

  2. Is there any reason to express a function instead of declaring it? i.e, to express a function as a var, let or const instead of simply declaring it with the function keyword? What are the advantages of each way? I read here that besides hoisting, it is entirely a stylistic decision. Wouldn't it then, be safer to always declare functions rather than expressing them? I must be missing something basic here.

Yoav Vollansky
  • 193
  • 3
  • 13
  • Possible duplicate of [Whats the need and use of nested functions in JavaScript](https://stackoverflow.com/questions/44482643/whats-the-need-and-use-of-nested-functions-in-javascript) – AndrewL64 Dec 18 '18 at 20:59
  • 1
    It seems that wrapping with IIFE is only needed to apply strict mode to the inner function. – hindmost Dec 18 '18 at 21:02
  • @AndrewL, thank you. I updated the question to refer to the general case. I there any benefit for doing so in the specific example, though? – Yoav Vollansky Dec 18 '18 at 21:07
  • sounds like a bad tutorial, tbh. there's no benefit unless you consider strict mode a benefit. `const sum = (...xs) => xs.reduce((a,b) => a + b, 0)` is really all you need. – Mulan Dec 18 '18 at 21:11
  • @user633183 I know, right? it's a bit discouraging since that website is ranked #1 on most places I checked. Perhaps they just wanted to demonstrate the *capability* of coding this way, but it is unnecessary and irrelevant to this specific drill and is only causing confusion. – Yoav Vollansky Dec 18 '18 at 21:20
  • 1
    @hindmost which of course is not necessary at all, they could just have put the directive in the inner function. – Bergi Dec 18 '18 at 21:27

4 Answers4

1

Using a anonymous function that is immediately called like in your example is often done for the sole purpose of isolating the scope of your code. In this case in particular, the use of "use strict" restricts the strict mode exclusively to the code within the top-level function.

As you said, you could just have a function instead of two, but the result isn't the same:

const sum = (function() {
  "use strict";
  var x = something(); // strict mode enforced here
  return function sum(...args) {
    return args.reduce((a, b) => a + b, 0);
  };
})();

And here:

var x = something(); // strict mode not enforced here
function sum() {
    "use strict";
    return arguments.reduce((a, b) => a + b, 0);
};

Additionally, while in the second approach the function must necessarily be declared on the global scope, in the first approach you could have many functions declared inside the top-level one without polluting the global scope.

JCOC611
  • 19,111
  • 14
  • 69
  • 90
0

In partial answer to number 2, a named function will report its name on stack traces while an anonymous function assigned to a variable or constant will not. So, this slightly favors just declaring functions.

However, you can name a function and assign it to a variable or constant without any problem like this:

let sum = function sum(...args) {
  return args.reduce((a, b) => a + b, 0)
}

Which, if you prefer assigned functions, gives you the best of both worlds.

Guy Royse
  • 2,739
  • 12
  • 9
0

re your first question: the construct used above makes sense when functions are used to package a module and emulate namespace (or package) scope. All top-function local vars would automatically be 'package' scoped. In the example above this is not used so I also think it's overengineered

re second question — anonymous fn, var and let have significantly different visibility. That often matters in design and could help you control better what you need exposed. that's the only reason I can think of.

gdanov
  • 312
  • 2
  • 12
0

1-This is what is called an IIFE. An Immediately Invoked Function Expression. And it has several avantages: first it's a way to create OOP like functionality like private and public functions, then it's a way to enclose things so they don't pollute global namespace. What happens if you declare a global function, and some library you use decalres the same function name ? The last one wins and this creates difficult to find bugs. This is also a way to create modules (read more about modules here).

2-depends on the logic used by the code's author and the way things are organized. It tends to be more concise to use vars instead of function. After the advent of array functions this became more and more common. But it's still your choice.

Nelson Teixeira
  • 6,297
  • 5
  • 36
  • 73