Eloquent JavaScript: Closures

Hi! I am browsing through some materials to understand scope and closures, and I stumbled upon this curious code snippet in Eloquent JavaScript:

function multiplier(factor) {
  return number => number * factor;
}

let twice = multiplier(2);
console.log(twice(5));
// → 10

What I do not understand is how the function multiplier knows what is number? Should it not be returned as undefined? I mean, if I pass 2 to the function, it returns some number and multiplies it by two, but the number has not been declared anywhere in the code. Could someone walk me through this example?

1 Like

multiplier return a function, number is the parameter of the returned function - that second function has just been stored in twice, but has not been called yet

you can also do multiplier(2)(5) and it will still return 10

2 Likes

Oh, yeah, it may look confusing. What you are looking at in the return statement is, as @ilenia mentioned, a function, and in specific, arrow function. So, in this case, “number” is just a placeholder variable. Let’s rewrite it into a standard function:

function multiplier(factor) {
  return function(number){
    return number * factor
  }
}

let twice = multiplier(2);
console.log(twice(5));
// → 10

As you see, we have two functions:

  • multiplier, that accepts a parameter of “factor”,
  • and inside it, an anonymous function that accepts a “number”.

Now, see what happens if we call multiplier with only one parenthesis:

multiplier(2)
// → ƒ (number){
    return number * factor
  }

We did invoke the function but what we are getting is the definition of the anonymous function nested inside. In order for this to work, we need to invoke this one as well, and so:

multiplier(2)(5)
// → 10

As you see, we provided first the argument to the multiplier function (or, what we called “factor”), and then another one to the anonymous function (what we called “number”).

Say we want to have a function that always doubles or triples the number. It would be repetitive to always say multiplier(2)(anotherArgument) or multiplier(3)(anotherArgument). In this case, it’s better to save it to a variable, just like in the Eloquent JS example:

let twice = multiplier(2);
console.log(twice(5));
// → 10

Hope this helps!

To add here, this has nothing to do with closures or any scope tricks, it’s a very straight-forward flow. This technique called Currying: https://en.wikipedia.org/wiki/Currying

Currying has everything to do with closures actually, in that the returned curried function closes over all the previous parameters.

1 Like

Oh shoot! @snigo, never reply on forum while watching New Pope!