Objective
Read a lot of other blog before this concept and the actual application of the closure, for its understanding has a number of general concepts, and today repeat reading, the closure of their understanding of the record, to consolidate understanding of the role.
Execution Environment and scope
When it comes to closures, the first thing to say is the concept of execution environment. The execution environment defines the other data that variables and functions have access to, and determines their behavior. Each execution environment has a variable object associated with it, and all variables and methods defined in the environment are stored in the object. Although we cannot access this object in our code, the parser uses it in the background. The global execution environment is what we call the Window object, each function has its own execution environment, all the code in an execution environment has been executed, the environment is destroyed, The variables and methods saved in the environment are also destroyed (the global execution environment knows when the application exits or when the Web page or browser is closed)
Each function in its own execution environment, when the execution of the flow into a function, the function of the environment will be pushed into an environment stack, after the function is finished, the stack will eject the environment, return control to the previous environment. When the code executes in an environment, it creates a scope chain for the variable object.
Scope chain
Purpose: Ensures an orderly access to all variables and functions that the execution environment has access to. The front end of the scope, which is always the variable object of the environment in which the current execution code resides. If the environment is a function, the active object is used as the variable object. The active object includes only one variable at the beginning, the arguments object (which does not exist in the global object). The next variable object is the containing external environment, and the variable object for the global execution environment is always at the very end of the scope chain.
The internal environment can access all external environments through the scope chain, but the external environment does not have access to any one of the variables and function names in the internal environment.
Life cycle of an active object
In general, when the function is finished, the execution environment is destroyed, and the local active object of the environment is destroyed, and memory only holds the variable object of the global execution environment, but if the function forms a closure, it returns another function in the function. In this function, the active object containing its (outer) function is added to the scope chain, since the active object is also in the scope chain of another function, so it is not destroyed, kept in memory until the closure function is destroyed.
The formation characteristics of closures
- Return another function in one function
- In this additional function can access the local variables and methods of the function
- These local functions and methods are kept in memory
function fn() { var a = 1; return function() { a++; return a; }}var f = fn();f();f();
The role of closures
- The
-
Encapsulates variables that encapsulate variables that do not need to be exposed to the global as private variables.
var mult = (function () {var cache = {};return function () {var args = Array.prototype.join.call (argument S, ', '); if (Cache[args]) {return Cache[args]}; var a = 1; for (var i = 0,len = Arguments.length; i < Len; i++) {a = a * arguments[i]; } return Cache[args] = A;}}) ();
The Refinement function is a common technique in code refactoring. If some code in a large function can be independent, we can encapsulate it in a separate small function, which facilitates the reuse of functions, the independent small function if there is a good name, itself plays a role in annotation. If these small functions do not need to be used elsewhere in the program, it is best to encapsulate them with closures.
var mult = (function () {var caculate = function () {//closed caculate function var a = 1; for (var i = 0, len = arguments.length; i < Len; i++) {a = a * arguments[i]; } return A;}; return function () {var cache = {}; var args = Array.prototype.join.call (arguments, ', '); if (Cache[args]) {return Cache[args]; } return Cache[args] = caculate.apply (null, arguments);}}) ();
Continuation of the lifetime of local variables
var report = function(src) {var img = new Image();img.src = src}report(‘http://baidu.com/getUserInfo‘);
Use closures to enclose IMG variables
var report = (function() {var imgs = [];return function(src) { var img = new Image(); imgs.push(img); img.src = src;}})();
Closures and memory management
We often say that excessive use of closures leads to memory leaks, in fact because we form circular references during the use of closures, which can lead to memory leaks if some DOM nodes are kept in the closure scope chain.
To resolve a memory leak caused by a circular reference, we need to set the variable in the circular reference to NULL
function assignHandler() { var element = document.getElementById(‘div‘); element.onclick = function() { // 创建了闭包,这个闭包又创建了一个循环引用 alert(element.id); }}
You can use the following code to dismiss a circular reference to resolve a memory leak
function assginHandler() { var element = document.getElementById(‘div‘); var id = element.id; // 将elemnt.id的副本保存到一个变量中,解除循环引用 element.onclick = function() { alert(id;) }; element = null // 解除对Dom对象的引用,解决内存泄露问题}
Note: In the above code, Simply saving a copy of element.id to a variable, releasing the circular reference does not relieve the memory leak because the closure references the entire active object containing the function, which contains element, and it is necessary to manually set element to NULL, even if the element is not used directly in the closure.
Javascirpt's closure comprehension