Interactions between Closures
When more than one inner function exists, closures can have effects that are not as easy to anticipate. Suppose we pair our incrementing function with another function, this time incrementing by two:
function outerFun() { var outerVar = 0; function innerFun() { outerVar++; alert(outerVar); } function innerFun2() { outerVar = outerVar + 2; alert(globVar); } return {'innerFun': innerFun, 'outerFun2': outerFun2}; }
We return references to both functions, using a map to do so (this illustrates another way in which reference to an inner function can escape its parent). Both functions can be called through the references:
var globVar = outerFun(); globVar.innerFun(); // Alerts "1" globVar.innerFun2(); // Alerts "3" globVar.innerFun(); // Alerts "4" var globVar2 = outerFun(); globVar2.innerFun(); // Alerts "1" globVar2.innerFun2(); // Alerts "3" globVar2.innerFun(); // Alerts "4"
The two inner functions refer to the same local variable, so they share the same closing environment. When innerFun()
increments outerVar
by 1
, this sets the new starting value of outerVar
when innerFun2()
is called. Once again, though, we see that a subsequent call to outerFun()
creates new instances of these closures with a new closing environment to match. Fans of object-oriented programming will note that we have in essence created a new object, with the free variables acting as instance variables and the closures acting as instance methods. The variables are also private, as they cannot be directly referenced outside of their enclosing scope, enabling true object-oriented data privacy.