closure
Rhinoceros book: if a function variable can be saved in the scope of a function, it can be called a closure
Advanced Programming: closure refers to a function that has access to variables in the scope of another function (the function is not exported);
javascript you don't know: when a function can remember and access its lexical scope, a closure is generated, even if the function is executed outside the current lexical scope
function foo(){ let n = 0; }
//Example 1 function(){ let n = 0; function bar(){ console.log(n) } } //Example 2 // closure function fn(callback){ let num = 18 return callback(num) } fn(function(){ console.log([].shift.call(arguments)); })
The function of closures is to prolong the life cycle of variables
Conditions for forming closures?
- Function nesting
- Function export
- The scope of the parent function can be accessed
- When a function is executed, it causes the function to be defined or thrown
Closure thinking problem
- Can you get n in test?
- Why can't I get it n?
- What should I do if I want to get it
function fn(callback){ let n = 99 callback() } function test(){ console.log(n); } fn(test) //It may be seen in many cases, which is slightly different from the above function fn(callback){ let n = 99 return callback(n) } let res = fn(n => n) console.log(res);
Personal understanding and answer:
1. No 2. because test Function found scope in current function body n This variable will then go up to the next level and can't be found, 3. If you want to get it, you can callback()Inside, then test receive `perhaps` Return a function definition and then call it outside, so it can be printed to n The value of is actually because the function is still calling, and the scope of the upper level function has not been destroyed, which verifies that the function of closures is to prolong the life cycle of variables
Form of closure
1.The return value of the function is the function function foo(fn){ let n = 0; return function(){} } 2.The returned variable is a function function foo(){ let n = function(){} return n } foo() 3.Closure defined by global variable let outter; function foo(){ let a = 10; outter = function(){ console.log(a) } } foo(); outter() 4.The way of function parameters is very common let inner = function(fn){ console.log(fn()) } ;(function(){ let b = "local"; let n = function(){ return b } inner(n) })() 5.Cyclic assignment function foo(){ let arr = [] for (let i = 0; i < 10; i++) { arr[i] = function(){ console.log(i); } } return arr } let res = foo(); res.forEach(fn => { fn() })
I understand why closures can extend the scope of variables?
- Because each function call creates a new scope, and the parent environment will be preserved when the child function is used
- Using let/const, you can declare variables in the block scope (in the new environment, not in the global)
Make a question and understand the closure
function fun(n,o){ console.log(o); return { fun(m){ return fun(m,n) } } } //1. Ask what to print let a = fun(0) a.fun(1) a.fun(2) a.fun(3) //undefined 0 0 0
- Needless to say, why is the first undefined 0?
- Because when the child function is used, the parent environment (i.e. scope) will be retained, and then n in the parent function will be found. At that time, n passed in 0, so it is printed 0
Let's analyze the scope
//Pseudo code //Execute let a = fun(0) |-- fun(n,o)Scope n = 0 ,o = undefined //There is an internal function to execute. This scope is reserved //Execute a.fun(1) a : { fun(1) return fun(m,n) //(1,0) //At this time, the scope of the parent function will be reserved, m = 1, and then look up n and find n = 0 (here n is the first formal parameter of the fun function. Don't be confused) } //Execute a.fun(2) a : { fun(2) return fun(m,n) //(2,0) n will look up } //Execute a.fun(3) a : { fun(2) return fun(m,n) //(3,0) n will look up }
How about this?
function fun(n,o){ console.log(o); return { fun(m){ return fun(m,n) } } } //2. Ask what to print let b = fun(0).fun(1).fun(2).fun(3); //undefined 0 1 2
We also use pseudo code to analyze the scope
//Pseudo code //Execute fun(0) function(n,o){ //N = 0, o = undefined the scope variable has not been destroyed console.log(o) //Print undefined //Execute fun (0) fun(1) function(n,o){ //n = 1,o=0 console.log(o) //Print 0 //Execute fun (0) fun(1). fun(2) function(n,o){ //n = 2 ,o = 1 console.log(o) //Print 1 //Execute fun (0) fun(1). fun(2). fun(3) function(n,o){ //n = 3 ,o = 2 console.log(o) //Print 2 }(3,2) }(2,1) //At this time, n = 1 is found in the previous scope }(1,0) //At this time, n = 0 is found in the previous scope }(0)
- Nested layer by layer, the previous scope has not been destroyed
Can we understand this as the function of closures? Is to extend the life cycle of variables,
Why is it extended? Because the scope of the parent function will not be destroyed when the child function is in use
Change it again
function fun(n,o){ console.log(o); return { fun(m){ return fun(m,n) } } } let c = fun(0).fun(1); c.fun(2); c.fun(3);
- You should be able to answer this question directly
- undefine 0 1 1
summary
The function of closures is to prolong the life cycle of variables
Why? Because the scope of the parent function will not be destroyed when the child function is in use
Conditions for forming closures?
- Function nesting
- Function export
- The scope of the parent function can be accessed
- When a function is executed, it causes the function to be defined or thrown