1

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.

Housni
  • 39
  • 5
  • 1
    You're not assigning the `outerFunction` to a variable, you're assigning its return value (ie: `innerFunction`) to a variable (`newFunction`) and then calling it on the last line – Nick Parsons Nov 17 '22 at 10:46
  • thanks @NickParsons. I am getting close to understand it. can you suggest a source to understand this concept better? thank you! – Housni Nov 17 '22 at 10:55
  • https://javascript.info/ @Housni Checkout Lexical Environment from here. – Bipin Nov 17 '22 at 11:01
  • You can also check out [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) on MDN, as well as other related topics such as [first-class functions](https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function) or "higher-order functions". There is also [How do JavaScript closures work?](https://stackoverflow.com/q/111102) (the accepted answer there is quite technical, you can refer to the other answers if that's not your style) – Nick Parsons Nov 17 '22 at 11:01

2 Answers2

1

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 = addThreeNumbersPartial(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.

Dakeyras
  • 1,829
  • 5
  • 26
  • 33
1
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!
jswrr
  • 95
  • 7