Seeing as MDN’s page on closures defines it extremely well, I’m not going to reinvent the wheel here:

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).

Let’s unpack this concept a bit.

The first thing I want to point out is that whenever you define a function, you are making a choice about its lexical environment, whether intentional or unintentional, conscious or…maybe you’re unconscious. I don’t know.

In many cases, the lexical environment of a function is just the global scope, because that is where you created it. Don’t worry, there’s nothing wrong with that.

**But the value of a closure becomes more obvious when you intentionally enclose a function into its own lexical environment. **One of the ways you can do this is by wrapping it inside another function. You’ve now created a more specific, local scope.

Here’s an example:

	function rocket(name, fc) {
	  let _name = name;
	  let _fuelConsumption = fc;
	  let _gas = 100;
	  let _miles = 0;

	  function fly() {
	    while (_gas > 0) {
	      _miles++;
	      _gas -= _fuelConsumption
	    };
	    console.log(`${_name} flew ${_miles} mile${_miles === 1 ? '' : 's'}.`);
	  };

	  return { fly };
	};

	let teslaRocket = rocket('Tesla Rocket', 1);
	let sputnik = rocket('Sputnik', 1.5);

	teslaRocket.fly();
	// Tesla Rocket flew 100 miles.
	sputnik.fly();
	// Sputnik flew 67 miles.

Here we have a rocket function, which has some local variables, and an inner fly function. When I call rocket, it returns a unique instance of an object with the fly function stored inside that object (line 15). It’s important to note that I’m not actually calling fly yet. I’m just returning an object that has the fly function inside it.

Each time I call the rocket function, I’m returning a separate instance of the fly function, and that instance of fly is actually holding on to its own instance of its lexical environment, even after rocket has completed running.

That right there is the power of a closure: Each time I call rocket, I’m creating an instance of fly that has a persisting reference to a unique lexical environment.

You can see how this specific use case could be valuable if you’re trying to do something object oriented. We’ve encapsulated state and behavior in a persisting, reusable manner! And we didn’t use classconstructorthis, or new. How about that.

One other nice thing about doing object oriented programming in this manner is that your state is actually private and inaccessible compared to when you use class syntax from ES2015. You can’t access the name of a rocket with sputnik._name (unless you added it to the returned object of rocket on line 15, but you shouldn’t do that).

The power to keep private state truly inaccessible is a really good thing. It tells readers how the function should and should not be used. Keep private variables private. This also gives you the option to implement a true “read only” paradigm, if you wanted to.

For example:

	function rocket(name, fc) {
	  let _name = name;
	  let _fuelConsumption = fc;
	  let _gas = 100;
	  let _miles = 0;

	  function fly() {
	    while (_gas > 0) {
	      _miles++;
	      _gas -= _fuelConsumption
	    };
	    console.log(`${_name} flew ${_miles} mile${_miles === 1 ? '' : 's'}.`);
	  };

	  return { 
	    fly,
	    get name() {
	      return _name;
	    }
	  };
	};

	let teslaRocket = rocket('Tesla Rocket', 1);
	let sputnik = rocket('Sputnik', 1.5);

	teslaRocket.fly();
	// Tesla Rocket flew 100 miles.
	console.log(teslaRocket.name);
	// Tesla Rocket
	sputnik.fly();
	// Sputnik flew 67 miles.
	console.log(sputnik.name);
	// Sputnik

I’ve added name access in the object returned by rocket on lines 17–19, using get syntax. I can now read the _name property, but I don’t have the ability to change it. That’s exactly the kind of guardrail that I wanted to implement. Great success!

#closure #web-dev-bootcamps #code-camp #javascript #lexical-scope #visual studio code

Quick Wins With Code: Closures in JavaScript
1.05 GEEK