The introduction

In the following example, notice how the internal function form refers to the requiredWho variable defined in the external function formFamily. We need to know that JavaScript allows you to refer to variables defined outside of the current function.

function formFamily (){
    var requiredWho = "Father and Mother ";
    function form (who){
        return requiredWho + "need " + who ;
    }
    return form ("YingBao and MaoTan");
}
formFamily(); // "Father and Mother need YingBao and MaoTan"Copy the code

This example is almost identical to the above, except that instead of immediately calling f(“YingBao and MaoTan”) in the external function formFamily, the form function itself is returned. So the value of f is the internal function form, and calling f actually calls the form function. But even after the formFamily function returns, the form remembers the requiredWho value.

So what we need to know here is,Even if the external function returns, the current function can still reference variables defined in the external function. This means that you can return an internal function and call it later.

function formFamily (){
    var requiredWho = "Father and Mother ";
    function form (who){
        return requiredWho + "need " + who ;
    }
    return form;
}
var f = formFamily(); 
f("YingBao"); // "Father and Mother need YingBao"
f("MaoTan"); // "Father and Mother need MaoTan"
f("YingBao and MaoTan"); // "Father and Mother need YingBao and MaoTan"Copy the code

How does this work?

The external function formFamily defines the internal function form, which in turn refers to the two variables requiredWho and who in the formFamily scope. Whenever the form function is called, its code can refer to these two variables because the closure stores them. The form function is a closure.

Using the inner form function outside of the outer function formFamily, and referencing the variables of the outer function, forms a closure.

define

JavaScript function values contain more information than the code needed to execute when calling them. Moreover, JavaScript function values internally store variables that they may refer to that are defined in their enclosing scope. Functions that trace variables in the scope they cover are called closures.

Tips1: Functions can refer to variables defined in their external scope. Tips2: Closures have a longer lifetime than the functions that create them.

To optimize the

A function can refer to any variable in its scope, including parameters and external function variables. We use this to write the more general formFamily function.

function formFamily (requiredWho){
    function form (who){
        return requiredWho + "need " + who ;
    }
    return form;
}
var f = formFamily("Father "); 
f("YingBao and MaoTan"); // "Father need YingBao and MaoTan"
var m = formFamily("Mother "); 
m("YingBao and MaoTan"); // "Mother need YingBao and MaoTan"Copy the code

This example creates two completely different functions, f and m. Although they are both defined by the same form function, they are two very different objects.

Closures are one of the most elegant and expressive features of JavaScript. JavaScript even provides a more convenient syntax for building closure literals, called function expressions.

function formFamily (requiredWho){
    return function(who){
        return requiredWho + "need "+ who ; }}Copy the code

Note that this function expression is anonymous. We only want it to produce a new function value, we don’t want to call it locally, so there’s no need to name the function at all.

extension

Closures can update the values of external variables. Closures actually store references to external variables, not copies of them. Therefore, any closure that has access to these external variables can be updated. Here’s an example.

function box(){
    var val = undefined;
    return {
        set: function(newVal) { val = newVal; },
        get: function() { return val; },
        type: function() { return typeofval; }}; }var b = box();
b.type();  // "undefined"
b.set(13.2);
b.get();  / / 13.2.6
b.type(); // "number"Copy the code

The box function stores an internal value that can be read and written. This example produces an object with three closures, which are the set, GET, and Type attributes. They all share access to the val variable. The set closure updates the value of val, followed by calls to get and type to see the results of the update.

Knowledge supplement

function outter(){   
    var n = 0; 
    return function (){
        returnn++; }}var o1 = outter();  
o1();//n == 0  
o1();//n == 1  
o1();//n == 2  

var o2 = outter();  
o2();//n == 0  
o2();//n == 1Copy the code

The external function outter returns a function assigned to o1, which has access to n. Function that returns can access the variables inside, so n cannot be reclaimed because o1 uses it.

Function (){return n++; } contains a reference to the local variable n of the outer function outter, so when the outer function outter returns, the value of n is preserved (not collected by garbage collection), and continuous calls to o1() will change the value of n. The value of O2 does not change as o1() is called. The first call to O2 results in n==0. In object-oriented terms, o1 and O2 are separate instances and do not interfere with each other.

One drawback to closures is that closures can cause memory leaks.

The resources

  1. Book: Effective JavaScript 68 Great Ways to Write High Quality JavaScript Code
  2. Blog:The Practice of Functional Programming in JavaScript