closure

  clojure, javascript

Closure, which obtains access rights to variables in a local scope, involves scope stack, execution context, garbage collection mechanism, memory resident and performance issues. Closure cuts off garbage collection events generated by scope stack to realize memory resident of variables. The main application scenarios need cumulative effect, repeated cycle events, correlation of front and back events, etc. Therefore, in order to avoid serious performance problems, after completing the event task, the closure should be set to null to free up memory.

This article introduces the characteristics of scope stack in JS, i.e. first in and then out, global scope is located at the bottom of the stack, local scope is put into the stack in sequence according to compilation and execution order, it is put out of the stack in sequence after execution, variables are garbage collected, and memory is released. Knowing this feature, the global scope is always located at the bottom of the stack and garbage collection is always completed finally. As long as the scope with global effect is loaded in the local scope and garbage collection is blocked, the closure design is completed.

  • Example 1

function foo(x) {
    var tmp = 3;
    return function (y) {
        console.log(x + y + tmp);
        x.memb = x.memb ? x.memb + 1 : 1;
        console.log(x.memb);
    }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);
  • Example 2

function foo(x) {
    var temp = 3;
    return function (y) {
        console.log(x + y + (++temp));
    }
}
var bar = foo(2);
bar(10);
  1. Example 3

function badClosureExample() {
    var as = document.querySelectorAll('a');
    for (var i = 0; i < 4; i++) {
        as[i].onclick = new popNum(i);
        function popNum(oNum) {
            return function () {
                alert('单击第' + oNum + '个');
            }
        }
    }
}
badClosureExample();
  1. Example 4

 function badClosureExample() {
    var as = document.querySelectorAll('a');
    for (var i = 0; i < 4; i++) {
        (function (i) {
            as[i].onclick = function () {
                alert('单击第' + i + '个');
            }
        })(i);
    }
}
badClosureExample();

1, the variableiSaved to each paragraph object (pOn

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].i = i;
        pAry[i].onclick = function () {
            alert(this.i);
        }
    }
}
init();

2, the variableiStored in the anonymous function itself

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (pAry[i].onclick = function () {
            alert(arguments.callee.i);
        }).i = i;
    }
}
init();

3. Add a layer of closure.iPass to inner layer function as function parameter

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function (i) {
            pAry[i].onclick = function () {
                alert(i);
            }
        })(i);//调用时参数
    }
}
init();

4. Add a layer of closure.iPass to inner function as local variable

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function () {
            var index = i;//调用时局部变量
            pAry[i].onclick = function () {
                alert(index);
            }
        })();
    }
}
init();

5. Add a closure layer and return a function as a response event (note the slight difference from 3)

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = function (i) {
            return function () { //返回一个函数
                alert(i);
            }
        }(i)
    }
}
init();

6. UseFunctionImplementation, in fact, generates a closure for every function instance generated.

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = new Function("alert(" + i + ")");
        //new一次就产生一个函数实例
    }
}
init();

7. UseFunctionImplementation, pay attention to the difference with 6

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick =Function("alert(" + i + ")");
    }
}
init();
  • Example 5

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    }
};
alert(object.getNameFunc()()); //The Window
  • Example 6

function outerFun() {
    var a = 0;

    function innerFun() {
        a++;
        alert(a);
    }

    return innerFun; //注意这里
}
var obj = outerFun();
obj(); //结果为1
obj(); //结果为2