define

A combination of a function bound to (or surrounded by) references to its surrounding state (lexical environment) is a closure. That is, closures allow you to access the scope of an outer function within an inner function. In JavaScript, whenever a function is created, the closure is created at the same time the function is created.

— Source: MDN

Let’s look at some examples of closures:

// function as return value
function makeFun() {
  const msg = "Hello function";
  return function () {
    console.log(msg)
  }
}
const fn = makeFun()
fn()

// once
function once(fn){
  let done = false;
  return function(){
    if(! done) { done =true;
      return fn.apply(this.arguments); }}}Copy the code

The nature of closures

Functions are placed on an execution stack at execution time and removed from the stack when the function completes execution, but the scoped members on the heap cannot be freed because they are referenced externally, so the inner function can still access the members of the outer function.

Closures in action

  1. Given a set of data, take the square root of math.pow ()
// Do not use closures
Math.pow(4.2)
Math.pow(5.2)
// Closure implementation
function makePower (power) {
  return function (number) {
    return Math.pow(number, power)
  }
}
/ / square
let power2 = makePower(2)
let power3 = makePower(3)
console.log(power2(4))
console.log(power2(5))
console.log(power3(4))
Copy the code
  1. For example, a company calculates salaries for programmers at different job levels. Suppose:
  • S5: Basic salary 10000
  • S6: The basic salary is 20000
  • In addition, merit pay ranges from 2000 to 5000

We define base salary as base and performance salary as performance

/ / not closure
function makeSalary(base, performance) {
  return base + performance;
}
/ / basic
const S5 = 10000;
const S6 = 20000;
// Employee A, B, C....
let A,B,C; / /...
A = makeSalary(S5, 3000);
B = makeSalary(S6, 4000);
C = makeSalary(S5, 2000); .Copy the code

Let’s change it up a little bit using closures

/ / closures
function makeSalary(base) {
  return function(performance){
    returnbase + performance; }}/ / basic
const S5 = 10000;
const S6 = 20000;
const makeSalaryS5 = makeSalary(S5);
const makeSalaryS6 = makeSalary(S6);
// Employee A, B, C....
let A,B,C; / /...
A = makeSalaryS5(3000);
B = makeSalaryS6(4000);
C = makeSalaryS5(2000); .Copy the code

From the example above, we can see that using closures avoids passing in parameters that don’t vary much, such as base salary, each time, and instead generates a more readable function that takes only one parameter.

How to debug on the browser

Let’s take example 1 above

  • Step 1 Let’s break the point

  • Step 2 Start debugging

When we get to line 15, we can see that the power variable has not been released due to the closure. Closure: power: 2: Closure: power: 2: Closure Closure: power: 2: Closure Closure: power: 2: Closure Closure: Power: 2