I have recently studied the documentation of you-Dont-know-JS, and have a sudden understanding of closures that I have been studying but never understood or learned. The following is a summary of my study.
Related concepts:
Closures are easy to understand after you have learned the concepts you need to understand before you learn them. YDKJS explains scopes and closures.
Scope:
A scope is a set of rules that determine where and how a variable (identifier) can be looked up.
Lexical scope:
Lexical scope means that the scope is defined by decisions about where functions are declared at authoring time. JavaScript uses lexical scoping, also known as static scoping.
JS scope:
Global scope, function scope, new block scope in ES6. Function scope: Functions are executed using the scope chain that was in effect when they were defined. Functions are executed using the scope chain that was in effect when they were defined. Independent of the scope in which it runs (lexical scope, static scope). Variables declared in the body of a function and function parameters are local variables defined only within the function. Execute function scope now:
- Create namespaces with private scopes to avoid contamination of global variables.
(function IIFE(){ var a = 3; console.log( a ); / / 3}) (); console.log( a ); // ReferenceError: a is not defined // a variable defined in the immediate execution function, is an internal variable of the function, external access times ReferenceError.Copy the code
- Simulate block-level scopes.
for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i); }, 1000); } // 10 10sCopy the code
Modify the code to print 0-9:
for (var i = 0; i < 10; i++) { (function (j) { setTimeout(() => { console.log(j); }, 1000); })(i); } // 0 1 2 3 4 5 6 7 8 9Copy the code
The effect is equivalent to:
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Copy the code
Scope chain:
A scope chain is created when a function is defined. The purpose of scope chains is to ensure orderly access to all variables and functions that the execution environment has access to. The scope chain is always preceded by a variable object from the environment of the currently executing code, the next variable object from the containment environment, and the next variable object from the containment environment, continuing into the global execution environment. The inner environment can access all the outer environments through the scope chain, but the outer environment cannot access any variables and functions in the inner environment:
var globalKey = 1;
function outer() {
var outerKey = globalKey + 1;
function inner() {
var innerKey = outerKey + 1;
}
console.log(inner.prototype);
}
Inner; //ReferenceError: inner is not defined
Copy the code
The internal properties [[Scopes]] view the scope chain:
Closure:
A closure is a function that can remember and access its lexical scope, even when the function is executed outside of its lexical scope. No matter what method is used to pass an inner function outside its lexical scope, it maintains a reference to the scope it was originally declared in (the lexical scope query rule), and the closure is exercised whenever it is executed. Timers, event handlers, Ajax requests, cross-window messages, Web workers, or any other asynchronous (or synchronous!) Task, passing in a callback function and hanging some closures around it.
var scope = "global scope";
function checkscope() {
var scope = "local scope";
function f() { return scope; }
return f;
}
checkscope()() //"local scope"
Copy the code
Checkscope (checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope, checkScope)
function counter() { var n = 0; return { count: function () { return n++; }, reset: function () { n = 0; }}; } var c = counter(), d = counter(); c.count(); //0 d.count(); //0 c.reset(); c.count(); //0 --> 1 d.ount (); //1 --> 2Copy the code
Explanation 1: It is possible to define multiple nested functions within the same external function. These nested functions, called closures, share private variables. Reset () and count() share the variable count. Explanation 2: Each time the outer function is run, a new closure is generated, and the variables in each closure do not affect each other. The count of C and D do not affect each other.
Closure with this
This suddenly becomes clear: this is a binding that is created when the function is called, and what it points to is entirely determined by the point at which the function is called.
- New binding: call through new? Use the newly built object.
- Explicit binding: called by call or apply (or bind)? Uses the specified object.
- Implicit binding: called by the environment object that holds the call? Use that environment object.
- Default binding: Default: undefined in strict mode, otherwise global object.
function makeFunc() { var name = "Mozilla"; Function displayName() {console.log(this) // 1 console.log(name); } return displayName; } var myFunc = makeFunc(); myFunc(); //Window {Window: Window, self: Window, document: document, name: "The Window", location: location,... } //MozillaCopy the code
Explanation 1: The displayName function is executed in the global environment, and this refers to the Window. This uses the default binding here. Explanation 2: The name variable is determined from the lexical scope at which the function is defined.
var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { console.log('1... ',this); 1 console.log('2... ',this.name); return function() { console.log('3... ',this); // interpret 2 console.log('4... ',this.name); }; }}; object.getNameFunc()(); / / 1... {name: "My Object", getNameFunc: ƒ} //2... My Object //3... Window {Window: Window, self: Window, document: document, name: "The Window", location: location,... } / / 4... The WindowCopy the code
Explanation 1: The getNameFunc() function executes, and this refers to the environment object on which the function is called. This uses an implicit binding here. Explanation 2: The object.getNameFunc() expression returns a function that executes in the global environment, and this refers to the Window. This here belongs to implicit binding – implicit lost.
The last
Further study directions: closure usage scenarios, closures and memory leaks, etc., due to my limited ability, I will not expand. Above, welcome to discuss, if there are mistakes, welcome to correct, I hope to help you 😀