Syntax of Closures

function makeIncreaseByFunction(increaseByAmount) {
  return function (numberToIncrease) {
    return numberToIncrease + increaseByAmount;
  };
}

makeIncreaseByFunction(3)(10);

Updated for Clarity Can somebody explain why the (3)(10) is written the way it is? I understand that 10 is being supplied as an argument to the inner function, but why is syntactically notated like this? If we had three nested functions, would the arguments always be written in order as in (3)(10)(20)?

Answers:

Answer

With intermediate variable:

var increaseBy3 = makeIncreaseByFunction(3);
var foo = increaseBy3(10);

Without intermediate variable:

var foo = makeIncreaseByFunction(3)(10);

In both cases, the first invokation passes the argument 3 to makeIncreaseByFunction, and as a result it returns the inner function that has closed over increaseByAmount with the value of 3. Whether you create a variable for the intermediate function returned by makeIncreaseByFunction, or just invoke it directly, it does the same thing.


Can you explain a little bit more detail about how in var foo = makeIncreaseByFunction(3)(10); the 10 is getting to the inner function? It just looks syntactically different from how arguments usually get passed in Javascript to me. – ggg

makeIncreaseByFunction(3) returns a function, specifically the "inner function" defined inside makeIncreaseByFunction. As will all functions, you call it with the function ( arguments ) syntax. You can write it like this if it makes more sense to you this way:

( makeIncreaseByFunction(3) )(10)

What happens here is makeIncreaseByFunction(3) gets called first and returns the ?inner function?, and then we call ?inner function?(10).

If you were evaluating this by hand (I think this is what you meant by "syntactically"), you could think of it happening step-by-step like this:

// Original invocation
var foo = makeIncreaseByFunction(3)(10);

// Substitute the definition of makeIncreaseByFunction
var foo = (function (increaseByAmount) {
  return function (numberToIncrease) {
    return numberToIncrease + increaseByAmount;
  };
})(3)(10);


// Apply the parameter 3
var foo = (function (numberToIncrease) {
  return numberToIncrease + 3;
})(10);


// Apply the parameter 10
var foo = 10 + 3;

// Final result
var foo = 13;

Note: If you want to be technical, all we're doing here is two Beta reductions—but unless you have background with the Lambda Calculus that will probably confuse you more than it will help you!

Answer

makeIncreaseByFunction(3) would return function so the syntax for then calling it with 10 would be makeIncreaseByFunction(3)(10).

This is easy to understand as if you have a function foo (imagine that the return of makeIncreaseByFunction(3) is such a function, they are evaluated identically), you would then call it with 10 using foo(10).

As for how the value of 10 is being 'passed', this is the wrong way to thing about things.

You must realise that in Javascript functions are first class objects. Instead of passing the value to the inner function, you are creating a function that does what you want and then calling it with the outer argument.

It is the same as using a variable to add within a function in a non-functional language except functions can be dynamically created at runtime and the values of any variable in their definition can be set influencing their internal consistency.

The closure refers to the fact that the created function is a black-box which hides the variable used to initialize it, despite still using that variable to increment the value it is called with.

Answer

var increaseBy3 = makeIncreaseByFunction(3); is the exact same as (disregarding the local storage for the variable increaseByAmount):

var increaseBy3 = function (numberToIncrease) {
    return numberToIncrease + 3;
};

So of course now you can call increaseBy3(10) and get 13. increaseBy3 just references as anonymous function which returns its first argument plus 3.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.