3

Suppose we have a containerFunction with two functions defined within it:

var innerFunction1link;
var innerFunction2link;

function containerFunction() {
    var someInnerVariable = 1;

    innerFunction1link = innerFunction1;
    innerFunction2link = innerFunction2;

    function innerFunction1() {
        console.log("I'm 1 " + someOuterVariable + " " + (someInnerVariable++));
    }

    function innerFunction2() {
        console.log("I'm 2 " + someOuterVariable + " " + (someInnerVariable++));
    }
}


containerFunction();
var someOuterVariable = 42;

// Point A
innerFunction1link();
innerFunction2link();

someOuterVariable = "WAT?!";

// Point B
innerFunction1link();
innerFunction2link();

Now the question. According to "Secrets of The JavaScript Ninja" book, each closure will have its own private set of variables (including the ones defined later, like someOuterVariable):

private bubbles

So innerFunction1 and innerFunction2 referenced outside of containerFunction as innerFunction1link and innerFunction2link will have their "private bubbles" with full set of variables in them. At the "Point A" both functions will execute fine and will output:

I'm 1 42 1
I'm 2 42 2

Then, when I set someOuterVariable to "WAT?!", the output is:

I'm 1 WAT?! 3
I'm 2 WAT?! 4

How will value of someOuterVariable and someInnerValue be actually updated in both "private bubbles" (and what if there were 1000 of those bubbles)? Does it actually keep track of all the references to all variables? And if one closure updates someOuterVariable, how its value will be populated to other closure?

Update:

And even if innerFunction's will be defined in different contexts, they will still "share" variables:

function containerFunction1() {
    var someInnerVariable = 1;

    innerFunction1link = innerFunction1;

    function innerFunction1() {
        console.log("I'm 1 " + someOuterVariable + " " + (someInnerVariable++));
    }
}

function containerFunction2() {
    var someInnerVariable = 1;

    innerFunction2link = innerFunction2;
    function innerFunction2() {
        console.log("I'm 2 " + someOuterVariable + " " + (someInnerVariable++));
    }
}

containerFunction1();
containerFunction2();
var someOuterVariable = 42;

innerFunction1link();
innerFunction2link();

someOuterVariable = "WAT?!";

innerFunction1link();
innerFunction2link();

Output:

I'm 1 42 1 
I'm 2 42 1
I'm 1 WAT?! 2
I'm 2 WAT?! 2 

2 Answers 2

6

A better description than using private bubbles would be that each function keeps a reference to the scope in which it was defined.

It must be clear that it is a reference and not a copy.

This explains that both innerFunctions points to the same scope, and thus the same set of variables. And those variables can also be changed in the external scope or through any of the functions pointing to this scope.

As a complementary remark : a scope in JavaScript is created each time you call a function (there are also other scopes, most notably the global scope but also the ones you can create with with or try/catch).

Sign up to request clarification or add additional context in comments.

4 Comments

Ok, then what if innerFunctions will be created in different containers? Shouldn't they have different contexts? (I've added this to the question)
By "..." I meant non-changed part. Added it.
What I meant by "keeps a reference" is that it is a reference, not a copy of the external scope. That's why the change in someOuterVariable is reflected in the logs.
I'm saying this because by updating someOuterVariable I'm updating it for both inner functions. But I understand now, why it works. Additional thanks to see through the walls of your bubbles from Bergi :)
1

So innerFunction1 and innerFunction2 referenced outside of containerFunction as innerFunction1link and innerFunction2link will have their "private bubbles" with full set of variables in them.

Not really. Their bubbles are quite empty, but from inside them you can see through the walls of your bubbles into the bigger bubble of containerFunction. In there, you can see 4 variables: containerFunction, someInnerVariable, innerFunction1 and innerFunction2. And from that bubble you can see into the global bubble, with the innerFunction1link, innerFunction2link, someVariable, containerFunction and someOuterVariable variables.

So instead of having lots of having every variable duplicated in the bubbles, they are just pointers to the shared variables in a higher bubble. If they're updated from anywhere, you can see that from your private bubble as well.

Now replace every occurence of the word "bubble" with "scope" :-)

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.