One, what is closures
functionfoo () {varA = 2; //the lexical scope of the function bar () can access the internal scope of the function foo (). Pass the bar () function as a value. //Bar () declares within Foo () that it has a closure that covers the internal scope of Foo (), allowing the scope to survive until bar () is referenced at any later time. Bar () itself uses the internal scope of Foo (), so Foo will not be destroyed after execution. functionBar () {Console.log (a); } returnBar;}//Bar () can run normally and is executed outside of its lexical scope. varBaz =foo ();//after Foo () executes, its return value bar () function is assigned to the variable Baz and called Baz (), which is actually called the internal function bar (). Baz ();
Bar () still holds a reference to the scope, which is called a closure .
Regardless of whether an intrinsic function is passed outside the lexical scope by any means, it will have a reference to the original definition scope, and no matter where the function is executed, the closure will be generated.
function foo () { var a = 2; function Baz () { // 2 } Bar (baz);} function Bar (FN) { // closures }
var fn; function foo () { var a = 2; function Baz () { console.log (a); } = baz ();} function Bar () { // closed package }foo (); bar ();
The internal function timer is passed to the Settimeout,timer that covers the wait scope, so a reference to the message is retained. After wait executes 1000 milliseconds, its internal scope does not disappear, and the timer function retains the wait-scoped closure.
function Wait (message) { for (var i = 0; I <= 5; i++) { function timer () { console.log (i); }, I*1000);} }
If you use functions that access their respective lexical scopes as first-level value types and pass around, you can see how closures are applied to these functions. In timers, event listeners, Ajax requests, cross-window communication, WEB workers, or any other asynchronous (synchronous)
In a task, a closure is used whenever a callback function is used.
function Setup (name, selector) { function activator () { "activating:" + name); }); "Closure bot 1", "#bot_1""Closure bot 2", "#bot_2");
The function iife is not executed outside of its lexical scope, but at the scope where it is defined. A is found by ordinary lexical scopes rather than closures. Although Ieff itself is quite a good example of observing closures, it does create closures,
It is also the most commonly used tool to create closures that can be closed.
var a = 2;(function iife () { console.log (a);} ());
Loops and closures
for (var i = 0; I <= 5; i++) {
SetTimeout (function () {
Console.log (i);
}, i*1000);
}
Output 5 x 6 per second
the callback for the deferred function executes only after the loop has finished . When the timer is running, even if settimeout (..., 0) is executed in each iteration, all the callback functions are still executed after the loop is completed.
According to the scope principle, although the five functions of a loop are defined separately in each iteration, they are all in the global scope and actually have only one I.
More closure scopes are required, especially in the case of loops where the closure scope is required for each iteration.
This example cannot be achieved
for (var i = 0; I <= 5; i++) { (function() { function() { Console.log (i); }, I*1000); } ())}/ / Each delay function is closed in the scope created by the Iife in each iteration /// But here is an empty scope
It needs to have its own variables that are used to store I in each iteration.
for (var i = 0; I <= 5; i++) { (function() { var j = i; function () { console.log (j); }, J*1000); } ())}
Slightly improved
for (var i = 0; I <= 5; i++) { (function(j) { function() { Console.log (j); }, J*1000); } (i))}
Using Iife within an iteration will generate a new scope for each iteration, so that the callback for the deferred function can enclose the new scope within each iteration, and each iteration will contain I a variable with the correct value.
Using block scopes
for (var i = 0; I <= 5; i++) { = i; // block scope for closures function Timer () { console.log (j); }, J*1000);}
The let declaration for a For loop has a special behavior where the variable is declared more than once during the loop, and each iteration is audible. Each subsequent iteration initializes the variable with the value at the end of the previous iteration.
for (Let i = 0; I <= 5; i++) { function timer () { console.log (i); }, I*100 0);}
Module
functionCoolmodule () {varsomething = "cool"; varanother = [1, 2, 3]; functiondosomething () {console.log (something); } functionDoanother () {Console.log (Another.join (" ! " ) ); } return{dosomething:dosomething, doanother:doanother};}varFoo =coolmodule (); foo.dosomething ();//CoolFoo.doanother ();//1! 2! 3
This model is becoming a module, the most common way of implementing modules is exposed as modules, here is its variant.
First, Coolmodule () is just a function that must be called to create an instance of a module. If you do not execute an external function, neither the inner scope nor the closure can be created.
Second, Coolmodule () returns an object literal syntax {key:value, ...} To represent the object. This object contains a reference to an intrinsic function rather than an intrinsic variable. Outside to keep internal variables is hidden and private state. You can consider the return value of this object type as essentially a public APIfor the module.
The return value of this object type is eventually assigned to the external variable foo, which can then be used to access the API's property methods.
- It is necessary to return the actual object from the module, and an intrinsic function, such as jquery, can be returned.
Module mode requires two necessary conditions.
- There must be an external enclosing function that must be called at least once (each call creates a new instance of the module).
- The enclosing function must return at least one intrinsic function in order for the intrinsic function to form a closure in the private scope and to access or modify the private state.
When you need only one instance, you can implement a singleton pattern:
varFoo = (functionCoolmodule () {varsomething = "cool"; varanother = [1, 2, 3]; functiondosomething () {console.log (something); } functionDoanother () {Console.log (Another.join (" ! " ) ); } return{dosomething:dosomething, doanother:doanother};} ()); foo.dosomething (); //CoolFoo.doanother ();//1! 2! 3
The module is also a normal function, so you can accept parameters:
function Coolmodule (ID) { function identify () { console.log (ID); } return { identify:identify };} var foo1 = Coolmodule ("Foo 1" ); foo1.identify (); // "Foo 1"
Module mode another simple but powerful use is to name the object that will be returned as a public API:
varFoo = (functionCoolmodule (ID) {functionChange () {publicapi.identify=identify2; } functionidentify1 () {console.log (ID); } functionidentify2 () {Console.log (Id.touppercase ()); } varPublicapi ={change:change, identify:identify1}returnPublicapi;} ("Foo module") ; foo.identify (); //Foo ModuleFoo.change (); foo.identify (); //FOO MODULE
The modern modular mechanism
varMymodules = (functionManager () {varModules = {}; functiondefine (name, Deps, Impl) { for(vari = 0; i < deps.length; i++) {Deps[i]=Modules[deps[i]]; } Modules[name]=impl.apply (Impl, deps); } functionget (name) {returnModules[name]; } return{define:define, get:get}} ());
The core of this code is modules[name] = impl.apply (Impl, Deps). The wrapper function is introduced for the definition of the module, and the return value (module API) is stored in a list of modules that are managed by name
//Defining modules
Mymodules.define ("Bar", [],function() { functionHello (who) {return"Let me introduce:" +Who ; } return{Hello:hello};}); Mymodules.define ("Foo", ["Bar"],function(bar) {varHungry = "Hippo"; functionAwesome () {Console.log (Bar.hello (Hungry). toUpperCase ()); } return{awesome:awesome};});
// Use var bar = Mymodules.get ("bar" ); var foo = mymodules.get ("foo""Hippo" ); Foo.awesome ();
Both the Foo and bar modules are defined by a function that returns a public API. "Foo" even accepts an instance of "bar" as a dependent parameter and can use it accordingly.
JavaScript you don't know scope closure