“This is the third day of my participation in the First Challenge 2022. For details: First Challenge 2022”

JavaScript Advanced Programming (Version 3)

Closures are functions that have access to variables in the scope of another function.

The Definitive JavaScript Guide (6th edition)

Function objects can be related to each other through scope chains, and variables within the body of a function can be stored in the scope of the function, a property known in the computer science literature as closures.

The definitions of closures vary, and they are a little tricky to understand. All of these definitions are fine when we’re trying to state what a closure is. State what you think is the most correct definition, and then explain your statement through the application of closures

I briefly looked at the Function Definitions link in ES6

You can see that the Closure it defines is returned by the internal FunctionCreate

Let me give you my understanding of closures ——

First: Closures have two parts:

  1. function
  2. The variable of the lexical environment in which the function resides
  • By definition: the creation of a function forms a closure
  • A function that refers to a variable in its lexical context exists even if the lexical context does not exist

Insert your own thoughts:

  1. Put asideclosureThis gadget, under normal circumstances, after a function to perform, it will destroy the function of internal variables, but in practice there are many possible we also need to use these variables should be destroyed, such as the function returns a function (variable) refers to the outer function, this time we need to make the variables exist, so was bornclosure. The closure was created when the function was created because there were so many possibilities
  2. Function execution isThe stackStructure when executedInto the stack, no further action is required.Out of the stackWhen the function executes, it carriesclosureVariables that are referenced in the stack
function fooWrapper() {
	var x = 0
	function foo() {
		var xx = 1
		function fooInner() {
			var xxx = 2
			debugger
			console.log(x)
			console.log(xx)
			return xx
		}
		fooInner()
	}

	foo()
}
Copy the code

Open and execute the code above in the browser console: see the call stack and the variables it contains,

FooWrapper, foo, and fooInner are stacked, and variables in the scope of the stack can be seen in local, global, and the variables in the closure they carry

Application of closures

The definition of closures is really mysterious and mysterious. For a deep understanding of closures, it is better to focus on the application of closures

Closures are used everywhere

function foo() {
	var a = 1

	return function () {
		a++
		console.log(a)
		return a
	}
}

var getA = foo()

getA() / / 2

getA() / / 3
Copy the code

The above example is not very common for us, we often have this kind of situation in writing code, in addition to interview questions

In an interview, of course, this will happen again

var getA = foo()
getA() / / 2
getA() / / 3

var getB = foo()
getB() / / 2
Copy the code

Because when Foo executes again, a new closure is formed

Examples of this are the most basic features of closures: caching data, variable persistence, and ultimately, the variables inside the closure are active and can always be referenced

Let’s see how closures are used

Different processing is done by caching closure variables

  1. Application of single column pattern

Let’s take a simple example

// Check if you are in love
function inLove() {
	// You are the only single dog
	const persons = ['Single Dog']

	function addPerson() {
		persons.push('Single Dog')}return {
		addPerson,
		getRes: function () {
			return persons.length > 1}}}const love = inLove()
love.addPerson()
love.getRes()
love.addPerson()
love.getRes()
Copy the code

Example above: if one person is single, if another single dog comes along, you are a couple, and the next one is still a couple…

When an instance is instantiated for the first time in the singleton class, it is given a value. If it exists, the generated instance is not returned

class SingletonApple {
  constructor(){}static getInstance() {
    if(!this.instance) {
      this.instance = new SingletonApple();
    }
    return this.instance; }}Copy the code

Simulate block scope

  • A classic interview question
for (var i = 0; i < 5; i++) {
  setTimeout(function() {
      console.log(i)
  }, i * 1000)}Copy the code

Print out five 5’s in turn

I want to print every I (0, 1, 2, 3, 4) at once. How do I rewrite that

Of course you can just let

Let’s look at it in the form of closures

for (var i = 0; i < 5; i++) {
	(function(i) {
		setTimeout(function() {
				console.log(i)
		}, i * 1000)
	})(i)
}
Copy the code

We simply pass in the I of our current loop through a self-executing function (IFFE)

First of all, before rewriting, our setTimeout is delayed, the loop body executes normally, and setTimeout will be executed after the loop is completed. At this time, I is a global variable and has been set to the value 5 after the loop, so it is ok to use let. Through closure, we form our scope, and I is passed in as a parameter. I here is the value of I for the current loop

As an extension we can do event binding for node loops

Get a set of DOM node loops and bind it to a function that uses the variable I in the function as well

The function is currified

  • Function corrification refers to changing one function that takes n arguments to n nested functions that take only one argument

Let’s steal an example

function getAddress(province, city, area) {
	  return province + city + area
}
getAddress('jiangsu'.'wuxi'.'Lakeside')
Copy the code

Let me rewrite this by the Definition of Corritization

function getAddress(province) {
	return function (city) {
		return function(area) {
			return province + city + area
		}
	}
}

getAddress('jiangsu') ('wuxi') ('Lakeside')
Copy the code

Experience the benefits

var province = getAddress('jiangsu')
var wuxi = province('wuxi')
// At this time I want to acquire Nanjing
var city = province('nanjing')
var area = city('Basalt')
Copy the code

Does the closure feel a little bit better at this point

Partial function

  • The partial function is actually an upgrade of the Curryization, it does not have the curryization limit of 1 parameter, depending on the actual situation n parameters can be arbitrarily passed in multiple parameters at a time

Let’s move on to the next classic interview question

Implement the following method add(1) (2) (3) = 6;

add(1.2.3) (4) = 10;

add(1) (2) (3) (4) (5) = 15;
Copy the code
function add() {
	var arg = [... arguments]

	var calc = function () {
		var newArg = [... arguments]
		if(newArg.length) { arg.push(... newArg)return calc
		} else {
			return arg.reduce((cur, next) = > cur + next, 0)}}return calc
}

add(1) (2) (3.4) ()/ / 10
Copy the code

What if I were to write a Coriolization function

function currying(fn, length) {
  length = length || fn.length
  return function (. args) {
    return args.length >= length
        ? fn.apply(this, args)
      : currying(fn.bind(this. args), length - args.length) } }Copy the code

Modular applications

Closure view links are used in es6’s Module

Let me give you a simple example

function createModule() {
	var x = 1,
	y = 2
	z = 3

	return {
		x,
		y,
		z,
		add(fish) {
			return x + y + z + fish
		}
	}
}

exportModule = createModule()

exportModule.x
exportModule.y
exportModule.add('salted fish')
Copy the code

For WebPack, these packaging tools are all in the form of closures posted below: Closure Application 6 – The builder packs Webpack

The problem with closures causing memory leaks

Overusing closures can cause closure variables not to be collected by the garbage collection mechanism. The common case for using closures is a memory leak, which can occur when there is too much nesting and layers of closure variables are active

For more on the recycling mechanism of closures, check out Masami Seto’s article on how each browser handles different engines

conclusion

Sensory closures are a thing that came into being, they’re everywhere, and based on them there are a lot of applications and a lot of ways to write code, and based on the knowledge of closures, it’s even more critical to learn what they’re derived from.