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
  • Possible duplicate of Are there any OO-principles that are practically applicable for Javascript?
    – gnat
    Commented May 1, 2016 at 17:20
  • 4
    @gnat: The other question is about principals, not the basic features of OO. I think this is a good, focused question. Commented May 1, 2016 at 18:09
  • IIFE explained for those of us not familiar with the term. Commented May 1, 2016 at 18:34
  • push should recreate the array every time it is called. Encapsulating that in a function call won't make a difference. Commented May 1, 2016 at 19:04
  • @AdamZuckerman What do you mean by "should"? I want the code to work in a way that when I run push(1) I get [1] and then when I run push(2) I get [1, 2], not just [2]. Commented May 1, 2016 at 19:08

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? Commented 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
    Commented 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. Commented 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. Commented May 1, 2016 at 19:02

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.