Detailed explanation of closures in Javascript_Basic knowledge
Foreword: This is still an introductory article. There are several very important language features in Javascript - objects, prototypal inheritance, and closures. Among them, closure is a new language feature for programmers who use the traditional static language C/C. This article will start with examples to introduce the language features of Javascript closures, and combine it with some ECMAScript language specifications to enable readers to have a deeper understanding of closures.
Note: This article is an introductory article. The example materials are compiled from the Internet. If you are an expert, you are welcome to provide technical suggestions and opinions on the article. This article discusses Javascript. I don’t want to do a language comparison. If you are naturally uncomfortable with Javascript, please take a detour.
What is closure
What is a closure? Closure is Closure, which is a new feature that static languages do not have. But closure is not something too complicated to understand. In short, closure is:
A closure is a collection of local variables of a function, but these local variables will continue to exist after the function returns.
Closure means that the "stack" of a function is not released after the function returns. We can also understand that these function stacks are not allocated on the stack but on the heap
When defining another function within a function, a closure will be generated
The second definition above is the first supplementary explanation, extracting the subject, predicate and object of the first definition - closure is the set of 'local variables' of the function. It's just that this local variable can be accessed after the function returns. (This is not an official definition, but this definition should be more helpful for you to understand closures)
As a local variable, it can be accessed by the code within the function. This is no different from a static language. The difference with closures is that local variables can still be accessed by code outside the function after the function execution ends. This means that the function must return a "reference" pointing to the closure, or assign this "reference" to an external variable to ensure that the local variables in the closure can be accessed by external code. Of course, the entity containing this reference should be an object, because in Javascript, except for basic types, everything else is an object. Unfortunately, ECMAScript does not provide relevant members and methods to access local variables in closures. But in ECMAScript, the inner function (inner function) defined in the function object can directly access the local variables of the external function. Through this mechanism, we can complete access to the closure in the following way.
function greeting(name) {
var text = 'Hello ' name; // local variable
// Each time it is called, a closure is generated and the internal function object is returned to the caller
Return function() { alert(text); }
}
var sayHello=greeting("Closure");
sayHello() // The local variable text
is accessed through the closure
The execution result of the above code is: Hello Closure, because the sayHello() function can still access the local variable text defined within it after the greeting function is executed.
Okay, this is the legendary effect of closures. Closures have a variety of application scenarios and modes in Javascript, such as Singleton, Power Constructor and other Javascript modes that are inseparable from the use of closures.
ECMAScript Closure Model
How does ECMAScript implement closures? Those who want to learn more can obtain the ECMAScript specification for research. I will only give a simple explanation here, and the content also comes from the Internet.
When the function of the ECMAscript script is running, each function association has an execution context scene (Execution Context). This execution context scene contains three parts
The LexicalEnvironment
The VariableEnvironment
this binding
The third point, this binding, has nothing to do with closures and will not be discussed in this article. The grammar environment is used to parse variable identifiers used during function execution. We can imagine the grammar environment as an object, which contains two important components, environment record (Enviroment Recode), and external reference (pointer). The environment record contains local variables and parameter variables declared inside the function, and external references point to the context execution scenario of the external function object. The value of this reference in the global context scene is NULL. Such a data structure forms a one-way linked list, with each reference pointing to the outer context scene.
For example, the closure model of our example above should be like this. The sayHello function is at the bottom layer, the upper layer is the greeting function, and the outermost layer is the global scene. As shown below: So when sayHello is called, sayHello will find the value of the local variable text through the context scene, so "Hello Closure" is displayed in the dialog box on the screen. The functions of the variable environment (The VariableEnvironment) and the grammar environment are basically similar. Please refer to the ECMAScript specification document for specific differences.
Sample sequence of closures
Previously, I roughly understood what Javascript closures are and how closures are implemented in Javascript. Below we will help you understand closures more deeply through some examples. There are 5 examples below. The examples come from JavaScript Closures For Dummies (mirror). Example 1: Local variables in closures are references rather than copies
function say667() {
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() { alert(num); }
num ;
Return sayAlert;
}
var sayAlert = say667();
sayAlert()
So the execution result should be 667 instead of 666.
Example 2: Multiple functions bind the same closure because they are defined in the same function.
function setupSomeGlobals() {
// Local variable that ends up within closure
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() { alert(num); }
gIncreaseNumber = function() { num ; }
gSetNumber = function(x) { num = x; }
}
setupSomeGlobals(); // Assign values to three global variables
gAlertNumber(); //666
gIncreaseNumber();
gAlertNumber(); // 667
gSetNumber(12);//
gAlertNumber();//12
Example 3: When assigning functions in a loop, these functions will be bound to the same closure
function buildList(list) {
var result = [];
for (var i = 0; i var item = 'item' list[i];
result.push( function() {alert(item ' ' list[i])} );
}
Return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// using j only to help prevent confusion - could use i
for (var j = 0; j fnlist[j]();
}
}
The execution result of testList is that the item3 undefined window pops up three times, because these three functions are bound to the same closure, and the value of item is the last calculated result, but when i jumps out of the loop, the value of i is 4, so list The result of [4] is undefined.
Example 4: All local variables of the outer function are within the closure, even if this variable is declared after the inner function is defined.
function sayAlice() {
var sayAlert = function() { alert(alice); }
// Local variable that ends up within closure
var alice = 'Hello Alice';
Return sayAlert;
}
var helloAlice=sayAlice();
helloAlice();
The execution result is a pop-up window of "Hello Alice". Even if the local variable is declared after the function sayAlert, the local variable can still be accessed.
Example 5: Create a new closure every time the function is called
function newClosure(someNum, someRef) {
// Local variables that end up within closure
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
Return function(x) {
num = x;
anArray.push(num);
alert('num: ' num
'nanArray ' anArray.toString()
'nref.someVar ' ref.someVar);
}
}
closure1=newClosure(40,{someVar:'closure 1'});
closure2=newClosure(1000,{someVar:'closure 2'});
closure1(5); // num:45 anArray[1,2,3,45] ref:'someVar closure1'
closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar closure2'
Application of closure
Singleton:
var singleton = function () {
var privateVariable;
function privateFunction(x) {
...privateVariable...
}
Return {
firstMethod: function (a, b) {
...privateVariable...
},
secondMethod: function (c) {
...privateFunction()...
}
};
}();
This singleton is implemented through closures. Encapsulation of private members and methods is completed through closures. The anonymous main function returns an object. The object contains two methods, method 1 can access private variables, and method 2 can access internal private functions. What needs attention is the '()' at the end of the anonymous main function. Without this '()', the singleton cannot be generated. Because anonymous functions can only return a unique object and cannot be called from other places. This is how to use closures to generate singletons.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SublimeText3 Linux new version
SublimeText3 Linux latest version

SublimeText3 Chinese version
Chinese version, very easy to use

Atom editor mac version download
The most popular open source editor

SublimeText3 Mac version
God-level code editing software (SublimeText3)