2

I am learning about javascript closures and am having difficulty understanding the concept. If someone would be kind enough to guide me through this example, i.e., where inputs and outputs are going, I'd appreciate it.

var hidden = mystery(3);
var jumble = mystery3(hidden);
var result = jumble(2);

function mystery ( input ){
  var secret = 4;
  input+=2;
  function mystery2 ( multiplier ) { 
    multiplier *= input;
    return secret * multiplier;
  }
  return mystery2;
}
function mystery3 ( param ){
  function mystery4 ( bonus ){
    return param(6) + bonus;
  }
  return mystery4;
}
results;

Thank you.

leocreatini
  • 676
  • 1
  • 9
  • 18
  • 1
    possible duplicate of [How do JavaScript closures work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – dsgriffin Feb 18 '14 at 22:27
  • Agreed that this is a duplicate of the question that @null linked to, although stated with a contrived and hard-to-follow example. – Justin Lovero Feb 18 '14 at 22:36
  • This is from Code School, I don't understand how the answer was 122 and hoped that someone would show me. – leocreatini Feb 18 '14 at 22:40

1 Answers1

6

Let's analyze this step by step.

The first call is to mystery with an argument of 3.

What does mystery do? It defines a variable secret with the value 4 and then it adds 2 to input.

So after the first two lines of mystery, you have:

secret = 4;
input = 5;

Then you have a nested function called mystery2 which takes in an argument called multiplier. In the first line it multiplies input to multiplier, and then returns secret * multiplier. We don't know the values of multiplier, but we do know the values secret and input. You might be wondering how that is. Well, in JavaScript when you create a closure, it is lexically bound to the current scope. This is just a fancy way of saying that the closure "knows" about all local variables that were created in the same scope that the closure itself was created. This behavior applies to nested functions as well which is why they can behave as closures in JavaScript. So what this means is that mystery2, when it is eventually called, will have secret set to 4 and input set to 5. So this mystery2, which knows about these two values, is returned from mystery. So after execution, the variable hidden doesn't contain a value, instead it contains a reference to an instance of mystery2 where the values of secret and input are the ones I mentioned earlier.

What is the advantage of this? The advantage is that you can have multiple copies of mystery2, which "know" different values of input based on what was passed into mystery. So here, mystery is sort of behaving like a constructor for mystery2.

Now we have hidden pointing to an instance of mystery2. So in this case hidden is sort of an alias for our own special copy of mystery2.

In the next line, you call mystery3 and pass in hidden as an argument. What happens inside mystery3? Well mystery3 accepts a parameter called param, then it does something similar to mystery; it returns a function. What does this function do? It accepts a parameter called bonus. Then it does param(6) + bonus.

What does that mean?

What is param? It is the argument that was passed into mystery3. Since mystery4 behaves like a closure, it "knows" about param. But actually, what is param? Well, param is hidden, which points to our special instance of mystery2! Now here is where we actually evaluate mystery2: we call it with an argument of 6, which will be the value of multiplier. So now you have multiplier *= input. The value of input that mystery2 "knows" is 5. So we basically have 6 * 5, which means that multiplier is now set to 30. Then we return secret * multiplier, which is 4 * 30, which is 120. So what this means is that param(6) returns 120, which we then add to bonus. Keep in mind that this will happen only when we actually execute mystery4.

When do we execute mystery4? Well after we call mystery3, we return a copy of mystery4, which is then assigned to jumble. After that we call jumble(2). So what is jumble? It is essentially this:

function mystery4(bonus) {
    return param(6) + bonus
}

What is param? Well, that is basically mystery2:

function mystery2 ( multiplier ) { 
    multiplier *= input;
    return secret * multiplier;
}

Let's go over the calculations again. When we call param(6), we basically have multiplier set to 6 inside mystery2. mystery2 "knows" that input is 5 (it is what we calculated inside mystery). So multiplier *= input, means that multiplier is now 30. Then we do secret * multiplier, which is 4 * 30, which is 120. So the return value of param(6) is 120. To this value we add bonus inside mystery4. We called mystery4 with an argument of 2, so we have 120 + 2, which means that the final result is 122.

Hope this helps you out!

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295