The sea is wide by diving, the sky is high as birds fly. Hey how are you! I’m Molly
Closures have been a platitude, and different people have different understandings of closures. Today I’m going to talk about closures, and we’re going to discuss the topic of “closures”, hoping to rub out some different sparks.
Before we understand closures, we need to understand context and scope
context
When a browser engine parses JS code, it generally goes through two phases. Parsing phase and execution phase
Analysis stage: A piece of code to put it bluntly, it’s just a regular code text so js engine will get code parsing code in advance, the initialization process variables, parameters, function, expression, operator and so on to extract coexist, and the default assignment for undefined variable, function default to function block, determine the context and a series of preparations
Execution stage: execute the code line by line from top to bottom. When encountering the corresponding variable or function, go to the warehouse for matching execution
console.log(str);
console.log(fun);
var str = "molly";
let str1;
console.log(str1);
function fun(a, b) {
return a + b;
}
Copy the code
Definition: Context can be divided into the global context and local context, context determines the variable or function they can access what data, as well as their behavior (good) were fixed initialization phase, each a context has a variable object (environment), all of the variables and functions defined in this context will be stored in the variable object, We can’t access this variable object directly from the code, but we can see it through the break point.
The global context is destroyed before the program exits (such as closing the web page or exiting the browser), and the local context is destroyed after its code has finished executing
So what does this variable object look like? Take your time. Let’s move on
Context execution stack
Definition: Each function call has its own context. When the function is executed, the context of the function will be pushed onto a context execution stack. After the function is executed, the context execution stack will pop up the context of the function, returning control to the previous execution context.
// A simple example, breakpoints debug call stack and context variable objects
let a_name = Force "cat";
var a_sex = "Male";
var a = "111";
function a_molly(age) {
let a_like = "Love to learn";
var a_like2 = "Love sports";
a_say(a_like);
var a = "222";
console.log(a);
let test = "Coming?";
}
function a_say(a_like) {
let code = "Knock code";
console.log(a_like);
}
a_molly();
Copy the code
With the example code above, we set a breakpoint on the console to watch the call Stack execute
Notice the call Stack on the left and the scope on the right and the breakpoint location
By observing the breakpoint debugging results, we can draw the following conclusions:
- When the script is initialized, a global context is pushed to the bottom of all context execution stacks, i.e
Global
attribute - Each time a function is executed, a “function context” is appended to the execution stack.
- When the function completes execution, the corresponding “function context” is cleared
- Within each context, accessible data is identified
Scope and scope chain
When the code in the context executes, it creates a chain of scopes for the variable object. This chain of scopes determines the order in which the code at each level of context accesses variables and functions. The scope is the containment relation, and the global contains the local.
Conclusion:
Context relates variable objects to determine which data functions can access, while scope determines the rules for data access.
Simply put, the access rules for scopes can be summed up as follows: look-in access, inside access to the outside and outside access to the inside, which can be called the scope chain
Function parameters are considered variables in the current context and therefore follow the same access rules as other variables below.
closure
Now that we have a brief overview of “context” and “scope,” it’s nice to talk about closures
Definition of closure
Little Red Book: Closures are functions that reference variables in the scope of another function
MDN: A combination of a function bound (or surrounded by) references to its surrounding state (lexica environment) is a closure. That is, closures allow you to access the scope of an outer function within an inner function. In JavaScript, whenever a function is created, the closure is created at the same time the function is created.
A closure is a function that can read variables inside other functions. Local variables can be read only by subfunctions inside a function, so closures can be understood simply as “functions defined inside a function”.
To summarize: the execution of a function can trigger the definition of another function (function declaration, function expression) and can reference variables in the scope of another function. So this function is a closure
Why are there closures?
To sum up, we can know that the local scope can access the global scope, but the global can not access the local, two irrelevant parts can not access each other, so, as long as the mind does not slide, the method is always more than difficult, to solve this kind of problem, we need to adapt, the conclusion is: “closure”.
Closures are like Bridges that connect disparate scopes to each other.
Closures take advantage of variable environments and scope-chain access rules
The purpose of closures
Closures have two main uses
- You can read variables inside the function body
- Keep the closure’s variables in memory at all times
Closure form:
Think of the function as a first-class citizen, as an ordinary variable
1: Returns a function
function fun(){
var aaa = 111
return function(b){
returnAaa + B}} Fun ()() Classic scenario: anti-shake throttlingCopy the code
2: Returns a function variable
function fun(a){
let fn = function(b){
return a+b
}
return fn;
}
fun()()
Copy the code
3: as a global closure function
var call;
function fun(a){
call = function(b){
return a+b
}
}
fun()
call()
Copy the code
4: Passed as a function parameter
function fun1(fn){
fn() // The fn function is the closure
}
function fun2(){
let str = 'molly'
function fun3(){
console.log(str)
}
fun1(fun3)
}
fun2()
Copy the code
5: callback function
function ajax(data){
console.log(data)
}
function sync(){
const obj = {name:'molly'.a:a}
ajax(obj)
}
Copy the code
6: IIFE executes the function immediately
; ! (function(){... }); Classic scene:for(var i = 1; i <=5; i++){ (function(j){
setTimeout(function timer(){
console.log(j)
}, 0(I)} jquery custom wrapped plug-ins also start with immediate function executionCopy the code
Advantages of closures:
- You can access two unrelated scope variables
- As a sandbox, store variables
- Code encapsulation, tool functions
- Function as value, takes in and returns
Disadvantages of closures:
- Memory leaks
How do you avoid memory leaks?
- Point the function pointer to
null
, into the scope of garbage collection - The closure completes execution
function fun(a){
return function(b){
return a+b
}
}
let a = fun()
a=nullOr the closure also completes a()Copy the code
Js garbage collection mechanism can be roughly divided into two types: “tag cleanup” and “count references”. When a variable inside a closure is used in another function, it is not identified as garbage, but is resident in memory and is not cleaned up. This results in extra memory consumption
Ask questions?
Do you know of any scenarios or code that makes clever use of closures? Welcome to discuss in the comments section!
Thank you
Welcome to pay attention to my personal public number front end of the cat every day to push you fresh quality good article. Reply “benefits” and you will get my carefully prepared front-end knowledge gift package. May you go all the way with light in your eyes!
Interested partners can also add my wechat: Molly or front-end communication group and many excellent front-end siege lions to exchange technology, play together!