3

I have a variable which I want to use in only one function. I can write my code like this:

var theAnswerToLife = 42

var multiplyIt = function(x) {
  return ++theAnswerToLife * x
}

I have some other functions in that file, which don't use that variable. Therefore, in order to limit access to that variable to only the multiplyIt function, I could wrap it in an IIFE:

var multiplyIt = (function() {
  var theAnswerToLife = 42

  return function(x) {
    return ++theAnswerToLife * x
  }
}())

Now that variable is available only to the inner function. Such encapsulation obviously makes sense when I have more variables, but is it worth it with only one variable? IIFE syntax is quite heavy, and in a more complex code I could end up having like three nested IIFEs.

How to keep balance between encapsulation and code readability? Where's the borderline?


My environment is Node.js, so a variable defined outside any function won't be global, but will be only available in the module scope.

6

2 Answers 2

3

Given a variable which needs to have a scope beyond a single function call, yet be accessible by only one function, I believe it's okay to not introduce a new scope just for that one function as long as you don't make the variable global.

In other words, I'd put this variable at module scope. You should already have some kind of module system which prevents top-level variables from being accessed by other modules unless explicitly exported. That might mean the traditional IIFE module pattern, or common.js modules or some other format, but whatever it is it should be introducing a new non-global scope for each module, so just use that scope when an additional IIFE feels like overkill.

2
  • Could you also address the "where's the borderline?" question? For example, if I had three variables like that, should I wrap it in an IIFE or not? May 1, 2016 at 21:35
  • 2
    That quickly gets into personal preference territory, so in lieu of a specific (and realistic) example there's not a lot to say. For instance, my "default opinion" would be that if you suspect those three variables need to be isolated from the rest of the module, you might want to break up that module into smaller modules. But I can also think of cases where a closure around one variable or an IIFE or whatever makes perfect sense. It just depends.
    – Ixrec
    May 1, 2016 at 21:43
1

If your goal is to limit variable scoping, you are making the issue more difficult than necessary.

Consider this function that achieves the same goal with a much more limited scope, both for the internal variables and the function complexity:

function doIt(x) {
  var theAnswer = 42;

  return x * 42;
}

It does the same thing yours does, but without the added complexity of a Clojure or IIFE (Immediately Invoked Function Execution). It also does not expose theAnswer to the global variable pool.

Calling it with this code will result in an error on the last line:

var results = document.getElementById("results");
results.innerText = "Function(3): " + doIt(3); 
results.innerText += ", theAnswer: " + theAnswer;
2
  • I think you misunderstood my question. I used 42 as the value to keep the example as simple as possible, but note that it could be more complex, for example it could be a result of a function call. If I put that inside the function, the value would be regenerated with every function call. May 1, 2016 at 18:58
  • It doesn't matter that theAnswer is a constant in my example. It could be a function call. The point is that it is a resultant value. You would have to get a result when you pass a new argument to a function, so this isn't significantly different. May 1, 2016 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.