It’s you — closure

Many developers confuse anonymous functions with closures and use them interchangeably. Closures are functions that have access to variables in the scope of another function. A common way to create closures is to create another function inside one function. —————— from JavaScript Advanced Programming

Create a function inside a function. It’s like it says in the book. Superfluous explanation). I used to get this question a lot in interviews… I didn’t know it was all there was. The following needs to have a little js foundation, understand the scope to understand…

The journey of closures has just begun

Let’s start with the simplest ⬇️

function a(){
    var b = 10;
    return function() {
        return b
    }
}
console.log(a()()); / / 10
Copy the code

Look at the miracle!! We print the value of the local variable B in function A. It’s amazing… Aye?? You might say, well, my local variable, b, is equivalent to a constant, wouldn’t it be an effect if I did something like ⬇️?

function a() {
    var b = 10;
    return b
}
console.log(a());
Copy the code

Ok, there is no mistake, then we change a way ⬇️

function a(paramA) {
    return function b(paramB) {
        return paramA + paramB
    }
}

var variable10 = a(10);
var variable20 = a(20);

console.log(variable10(5)); / / 15
console.log(variable20(5)); / / 25
Copy the code

In the example above, when we execute the output variable10(5) and variable20(5), why do we get 5 compared to the 10 passed in when we execute a(10)? That’s what closures are for, to take local variables inside a function and add them up. Wait a minute! If you don’t understand, why is it a local variable? Then I can make it clearer by writing ⬇️

function a(paramA) {+var variableA = paramA;
  return function b(paramB) {
    return variableA + paramB
  }
}

var variable10 = a(10);
/** * a(10) is passed in. * * function a(10) { * var variableA = 10; * return function b(paramB) {* return variableA + paramB *} *} Var variable10 = function b(paramB) {* return 10 + paramB *} */
var variable20 = a(20);

console.log(variable10(5)); / / 15
console.log(variable20(5)); / / 20
Copy the code

From the comments above, you should already know what a closure is, which is to create a function inside an external function so that global calls to the inner function can access the local variables of the external function and use them.

There is only one truth!

Here’s an example from JavaScript Advanced Programming

function createComparisonFunction(propertyName) {

  return function (object1, object2) {
    var value1 = object1[propertyName];
    var value2 = object2[propertyName];

    if (value1 < value2) {
      return - 1
    } else if (value1 > value2) {
      return 1
    } else {
      return 0; }}}Copy the code

In this example, the two lines of var Value1 and var value2 access the variable propertyName in the external function, even though the inner function is returned and has been called elsewhere. This is similar to my example above.

var manA = { name: 'Conan Edogawa'.age: 7 };
var manB = { name: 'Shinichi Kudo'.age: 17 };
var whoOlder = createComparisonFunction('age');
// Return -1 if the former is less than the latter, return 1 bit if the former is greater than the latter, return 0 if both are the same size
console.log(whoOlder(manA, manB));  // -1, Conan is less than Shinichi
Copy the code

The example above is the same as the example we started with when we introduced closures, okay? is

var whoOlder = createComparisonFunction('age');
/** * var whoOlder = createComparisonFunction('age') { * var propertyName = 'age'; * return function (object1, object2) { * var value1 = object1['age']; * var value2 = object2['age']; * if (value1 < value2) { * return -1 * } else if (value1 > value2) { * return 1 * } else { * return 0; *} *} *} * Var whoOlder = function (object1, object2) {var value1 = object1['age']; * var value2 = object2['age']; * if (value1 < value2) { * return -1 * } else if (value1 > value2) { * return 1 * } else { * return 0; *} *} */
Copy the code

Point!! When a function is called, an execution context and the corresponding chain of scopes are created. Then, you can initialize an activation object. What is in this activation object? Arguments and other named parameter values are ⬇️

function a(paramA, paramB) {
    return paramA + paramB
}
a(1.2)
/** * what is the active object of this function?? Have three * arguments [1, 2] * paramA 1 * paramB 2 */
Copy the code

If I use variable A in an internal function, I will first check whether the internal function has declared variable A. If it does not, I will look for the external function. If the external function does not, I will look for the global execution environment. In order to read and write the value of a variable during function execution, we need to look for the variable in the scope chain, as shown in the following example (JavaScript Advanced Programming example)

function compare(value1, value2) {
    if (value1 < value2) {
        return - 1
    } else if (value1 > value2) {
        return 1
    } else {
        return 0}}var result = compare(5.10)
Copy the code

So the chain of scope for this is going to be

The best budo assembly in the world

I think everyone will meet a very, very classic question in the interview, the topic is:

There are ten

  • tags on the page, which is a list of ten items, you need to click on each li to output the corresponding index.

    Classic wrong answer:

    var list = document.getElementsByTagName('li');
    for (var i = 0; i < list.length; i ++) {
      list[i].addEventListener('click'.function () {
        console.log(i)
      })
    }
    Copy the code

    Now we all know that we’re printing the same number. Why is that? Let me write it another way:

    var list = document.getElementsByTagName('li');
    var i = 0;
    for (i; i < list.length; i ++) {
      list[i].addEventListener('click'.function () {
        console.log(i)
      })
    }
    Copy the code

    So we can see that when this code is done, before we hit Li, the global variable I is already the last number, so if we have ten Li’s, I is already going to be 10 based on the loop. So, when we click on li’s input global variable I, of course we get 10 every time.

    Correct answer:

    var list = document.getElementsByTagName('li');
    for (var i = 0;; i < list.length; i ++) {
      (function (i) {
        list[i].addEventListener('click'.function () {
          console.log(i)
        })
      })(i)
    }
    Copy the code

    In the for loop, each perform a, perform a since the callback function, and hand in the I as parameters, js function parameters is characteristic of a pass by value, can also be understood as we talked about earlier active objects, the adjusting function of the value of the active object inside a I so at this time to be performed on each li surveillance function of the output not as a global variable I, It is the I in the active object, because the loop does not execute the self-tuning function once, so each self-tuning function is independent of each other, so the output value of I is naturally different. Of course, some people would argue that using ES6 syntax is simpler:

    var list = document.getElementsByTagName('li');
     - for (var i = 0; i < list.length; i ++) {
     + for (let i = 0; i < list.length; i ++) {
      list[i].addEventListener('click'.function () {
        console.log(i)
      })
    }
    Copy the code

    ES6 has the concept of block-level scope, so the value of I will be locked every time, and the output will naturally be different.

    Where there are leaves, the will to fire burns

    I’m going to leave the closure here, and if there’s anything wrong with the closure, I’m going to correct it, because I don’t want to make mistakes. The purpose of this blog post is to give myself a new understanding of the concept of closures. I am more aware of active objects and scope chains, but there are a lot of things I haven’t written about, such as this pointing problem, how to deal with memory leaks, how ES5 mimics block-level scopes, private variables, private functions, module mode, etc. This is a closure can be extended out of the problem, this can be found in the “JavaScript Advanced Programming” chapter 7 section 4, calm down to see, I believe that it can be understood, at first do not understand, for a period of time to read again, each time will certainly have a different understanding.

    On the front end, it’s all right to go for trendy technology, because trendy technology has advanced ideas and can tell you how to program. But before programming, or need to learn the basis, the basis to figure out, will certainly js, the front end, there is a new understanding.


    I’m a front end warrior, a front end elementary school.