“This is the fifth day of my participation in the August More Text Challenge.

primers

Many beginners will feel that the concept of closures is very troublesome and complex, and even some people say that closures will cause memory leaks, which makes people curious and afraid of closures. In fact, closures are not mysterious and not difficult, and it can even be said that all functions in JS are closures, closures are approachable.

Some of the more vivid metaphors I’ve seen for closures

1. Closures are for the poor. 2. Closures are spies who infiltrate the enemy’s inner camp and bring us information. 3. The closure is Alice in Wonderland, who has been to a far place that the ministers have never been to. After returning, she tells the ministers about the wonderland that they have never seen. 4. Closures are the second generation of the rich, inheriting the assets of their parents and squandering their tenure. However, even if a child comes out of a crack in a stone, he or she can freely breathe the air and enjoy the sunshine. 5. In nature, water flows from high to low, but smart and naughty human beings hope that water can flow from low to high one day. Finally, one day, people invented the pump, so that people can use water more freely, more arbitrarily. The pump here is the closure.

What is a closure?

1. Closures prevent garbage collection by referring to variables. 2. A function that references a free variable in an outer scope constitutes a closure. The key is how to understand the closure word. Closure is really like a class’s private variable in PHP and Java. The variable can only be read or changed by the closure that references the variable. Closures can refer to multiple methods in a PHP or Java class. Each closure represents a method in the class, so some people call closures poor objects.

function foo(){
    let test =1;
    const bar1=function(){
        test ++;
        console.log(test);
    }

    const bar2 = function(){
        test = test+100;
        console.log(test);
    }

    return [bar1, bar2];
}

let arr = foo();

arr[0] ()/ / 2
arr[1] ()/ / 102
arr[0] ()/ / 103
arr[1] ()/ / 203
Copy the code

Lexical scope and dynamic scope

Closure is the inevitable result of lexical scope. If you understand lexical scope, you basically understand closure. There are two kinds of scope, one is lexical scope, the other is dynamic scope. Lexical scope is determined at code writing or definition time, whereas dynamic scope is determined at run time. Lexical scopes focus on where functions are declared, while dynamic scopes focus on where functions are called from. In JS, there is only lexical scope, not dynamic scope. Languages that use dynamic scoping include Perl, Lisp, and so on.

var name = 'Ming';

function foo() {
  console.log(name); // Will output xiao Ming or Xiao Hong?
}

function bar() {
  var name = 'little red';
  foo();
}

bar();
Copy the code

Foo is called with the scope defined, not the scope in which it was called. This is the lexical scope.

Why do many people find closures hard to understand?

In my opinion, there are two main reasons: 1. Some books and articles explain closures too hard to understand. This, eval, and with behave like dynamic scopes. This, in particular, refers to the object on which it is called, regardless of the object on which it is defined, and is used frequently. This can easily confuse beginners. This makes it harder to understand closures.

The purpose of closures

1. Encapsulate private variables

var person = function(){    
    // Variables are scoped inside functions and cannot be accessed externally
    var name = "default";       
       
    return {    
       getName : function(){    
           return name;    
       },    
       setName : function(newName){ name = newName; }}} (); print(person.name);// Direct access, the result is undefined
print(person.getName());    //default
person.setName("abruzzi");    
print(person.getName());    //abruzzi
Copy the code

2. Mimic block-level scopes

    var arr = ["a"."b"."c"."d"."e"];
    for (var i = 0; i < arr.length; i++) {
        (function(j) {
            var item = arr[j];
            setTimeout(function() {
                console.log(item);
            }, 1000 * (i + 1));
        })(i);
    }
Copy the code

Of course, because setTimeout is an asynchronous task, if no closure is added, all printed out is E. Here, the closure is used to force the function to remember the I variable at that time. Of course, after ES6 introduced the let keyword, it is easier to use let. 3. Another feature of a stored variable closure is the ability to save variables of an external function. The inner function retains references to the active variables of the external function, so the variables are not released. For example, the implementation of anti-shake relies on closures

function debounce(fn, wait) {
  var timeout  // The closure method defines a global variable, which is the core of the implementation of the anti-shake function
  return function () {
    var context = this,
    args = arguments
    clearTimeout(timeout)
    
    timeout = setTimeout(function () {
      fn.apply(context, args)
    }, wait)
  }
}
window.addEventListener('scroll', debounce(scrollHandler, 500))
Copy the code

The core of this anti-shake function is to store the variable timeout. If the closure is not used, the timeout variable will be re-initialized every time the Scroll event is triggered, so the anti-shake effect cannot be achieved.

Misconceptions about closures. Do closures really cause memory leaks?

Closures do not cause memory leaks, but memory cannot be collected because previous versions of IE9 used different garbage collection for JScript objects and COM objects. This is an IE problem. Closures have nothing to do with memory leaks. Do closures cause memory leaks?

conclusion

Closures are a logical consequence of lexical scope. Functions that refer to external free variables are closures, and closures are not at all mysterious or scary.

Refer to the article

Lexical scope VS dynamic scope What is a closure? What are closures used for? Do closures cause memory leaks?