I am trying to understand closures, and I have this example below
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log('outer variable: ' outerVariable)
console.log('inner variable: ' innerVariable)
}
}
const newFunction = outerFunction('outside')
newFunction('inside')
the part that I don't understand is when we assign the outerFunction function to a variable (the last two lines), then call the variable as a function passing another argument. I have no idea what happened in there.
CodePudding user response:
Javascript doesn't have native support for Currying, which is when you take a function with multiple arguments and make a partial call to it.
A call to a Javascript function or method with only some arguments supplied will set all unspecified arguments to undefined
. The function will not return a partial function with some parameters already set, instead it tries to complete function execution with some undefined parameters.
What we can do instead is create a new function within a function and then return it. This works because functions can be treated like variables in JavaScript. Like any other variable that is returned, the new function continues to exist even after it leaves the closure of its parent function. However other values defined in that closure are no longer in scope.
This is no different in principle to returning an object {a: someVar, b: someOtherVar}
from a function where someVar
and someOtherVar
are set inside the function. someVar
and someOtherVar
variables disappear when the closure ends, but their values are now in the object that is returned.
It helps to think of closures as limiting what variables are accessible, rather than straight-up deleting data as soon as they end.
An example of currying:
const addThreeNumbers = (a, b, c) => {
return a b c;
}
// does not work as we would like it to
let addTenToTwoNumbers = addThreeNumbers(10); // value will be 10, rather than a curried function
let thirty = addTenToTwoNumbers(10, 10); // invalid, will break
const addThreeNumbersPartial = (a) => {
return (b, c) => a b c;
}
//now we can do this
addTenToTwoNumbers = addThreeNumbers(10);
thirty = addTenToTwoNumbers(10, 10);
The reasons this is useful are not immediately obvious, but JavaScript's ability to create and modify functions on the fly like this is incredibly powerful. I recommend reading up on functional programming if this is a topic that interests you.
CodePudding user response:
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log('outer variable: ' outerVariable)
console.log('inner variable: ' innerVariable)
}
}
const newFunction = outerFunction('outside')
Now you can imagine newFunction
to be:
function newFunction(innerVariable) {
console.log('outer variable: ' 'outside')
console.log('inner variable: ' innerVariable)
}
outerFunction
is kind of a function factory. It produces a new function with some value now "baked in", in this case outerVariable
. newFunction
now only references one external parameter, namely innerVariable
.
Or with a different example:
function makeGreeterFunction(greetWord) {
return function greet(name) {
console.log(greetWord " " name "!")
}
}
const helloGreeter = makeGreeterFunction('hello')
const welcomeGreeter = makeGreeterFunction('welcome')
helloGreeter("Tony")
// Hello Tony!
welcomeGreeter("Tony")
// Welcome Tony!
CodePudding user response:
thank you all! I understand now. I upvoted your answers but it doesn't show up because I need at least '15 reputations'.@Dakeyras @jswrr