What is the call stack
- Js creates a global context during execution and pushes the global context onto the stack
- When a function is executed, an execution context for that function is created
- When a function completes execution, the execution context of that function is removed from the stack,
- During execution, the function execution context is continuously pushed in and out of the stack
- When global code execution is complete, push the global execution context off the stack. At this point, program execution is complete
function func1() {}function func(b, c) {
func1()
}
func()
Copy the code
The execution stack structure of the above code is as follows (see the call stack at the interrupt point inside func1). The bottom anonymous is the global execution context. During execution, the function execution context is continuously pushed off the stack until the stack is empty and the program is finished
Scope and scope chain
A scope is the accessible range of variables and functions in a program. There are three types of scopes
- The global scope is accessible to any code
- A function scope can only be accessed inside a function
- Block-level scopes are available within scoped blocks
Note: The object is not a scope, just a data structure
var myname = "External"
function showName(){
console.log(myname);
if(0) {var myname = "Internal"
}
console.log(myname);
}
showName()
// Print two undefined
Copy the code
Analyze the code above
- The variable declared by var is promoted to the top of the current scope. Assignment is not promoted, so both prints access myname inside the function, so undefined is printed
The scope chain
First look at a piece of code and try to guess the output
function bar() {
console.log(name)
}
function foo() {
var name = "Internal"
bar()
}
var name = "External"
foo()
Copy the code
After careful analysis of the first thought, the output should be internal, according to the search order of this variable, it must print ‘internal’, but the result is… So let’s do a step by step analysis, and let’s first look at what is a scope chain
Scope chain: The variable environment of each execution context contains a reference to the external execution context. For example, in the above example, name is not found in the bar function. The current external reference refers to the function context
According to the logic of scope chain, why find the variable whose name is external, should not be internal?
This is because the scope chain is determined by the lexical environment, and you need to know the order in which the variable’s scope chain is found, as well as the lexical scope
Lexical scope: The lexical scope is determined by the position of the function declaration in the code, so the lexical scope is static and depends on the position in the code structure, not the relative order in the call stack
In the above example, bar is defined globally, so the upper execution contexts of bar and Foo are both global execution contexts by lexical scope, so the scope chain is both foo -> global, so the problem is solved
Modify the above code as follows to put the bar function declaration inside the foo function
function bar() {
console.log(name)
}
function foo() {
var name = "Internal"
function bar() {
console.log(name)
}
bar()
}
var name = "External"
foo()
Copy the code
The search order for the function’s scope chain is bar –> foo –> global.
closure
Let’s start with some code:
function foo() {
var myName = " test1 "
let test1 = 1
const test2 = 2
var innerBar = {
getName: function () {
let test = 'testGetName'
console.log(test1)
return myName
},
setName: function (newName) {
let test = 'testGetName'
myName = newName
}
}
return innerBar
}
let global = 'global';
var bar = foo()
bar.setName(" test2 ")
bar.getName()
console.log(bar.getName())
Copy the code
According to the rules of lexical scope, getName and setName inside Foo can access variables in foo. When foo completes, foo’s execution context is removed from the stack, but since the two inside functions still reference variables defined in Foo, these variables are closures
So closures are, the inner function always has access to the variables declared by the outer function, and even after the outer function has finished executing, the variables that the inner function refers to the outer function are still stored in memory, and the set of variables is the closure, and those variables are contained in foo, so it’s called the closure of Foo. The closure is in the browser closure.
You can see that only myName and test1 traversals are included in the closure. Variables that are not used by the internal function do not reside in memory and are not included in the closure
One last piece of code, understanding scoped chains and closures
var bar = {
myName:"time.geekbang.com".printName: function () {
console.log(myName)
}
}
function foo() {
let myName = " test1 "
return bar.printName
}
let myName = " test "
let _printName = foo()
_printName() // test
bar.printName() // test
// Print test for both,
// For the first: Because the printName function that's returned is defined outside of the function, inside the bar, so by the rules of lexology, it's going to start in the scope that printName is defined in because there's only one global scope, so it's going to find the global myName, and notice that the object is not really a scope, it's just a data structure, The rules for scoping chain searches are lexical scoped
// For the second: as for the first, it explains that the object is not a scope, except for the execution context of the function, which is the global context, without closure operation
var bar = {
myName:"time.geekbang.com".printName: function () {
console.log(myName)
}
}
function foo() {
let myName = " test1 "
return function () {
console.log(myName)
}
}
let myName = " test "
let _printName = foo()
_printName() // test1
bar.printName() // test
// Some changes were made to put foo's return function directly inside the function, so that when the return function looks for variables that do not exist in its own context, it looks up and finds foo's closure, followed by global
Copy the code
So far, these are the current understanding of these issues, may have a new understanding in a few days, constantly learning, constantly correcting and updating their understanding, is slow progress. Come on!!