What is scope?
Scope is the area of a program’s source code where variables are defined.
A scope specifies how to find a variable, that is, determine what access the currently executing code has to the variable.
JavaScript uses lexical scoping, also known as static scoping
Static scope & dynamic scope?
- Static scope: The scope of a function is determined when it is defined
- Dynamic scope: The scope of a function is determined when the function is called
Look at an example:
var value = 1;
function foo() {
console.log(value); // ?
}
function bar() {
var value = 2;
foo();
}
bar()
Copy the code
Suppose we look at the problem from a static scoping perspective:
Foo (value = 1); foo (value = 1); foo (value = 1); foo (value = 1)
Suppose we look at the problem from a dynamic scoping perspective:
When we execute foo, we still look inside foo to see if there is a local variable value. If not, the value variable is looked up from within the scope of the calling function, that is, the bar function, so the result prints 2.
As mentioned above, javascript is statically scoped, so the output is 1
Execution context
The javascript engine does not execute the code line by line, but piece by piece. Before executing the code piece by piece, the engine will perform a preparatory work, namely lexical analysis, such as variable promotion, function promotion, repeated promotion filtering, etc. Jacvascript you Don’t Know is devoted to javascript lexical analysis.
For example, we can think of a JS file as a piece of code that the javascript engine performs a lexical analysis of before executing
console.log(value) // undefined
var value = 'hello world'
Copy the code
That’s why the code above says undefined instead of value is not defined, right
So one of the questions here is how does javascript differentiate between pieces of code? Before ES6, there were three: global code, function, and eval code
Again, the concept of an Execution Context stack (ECS) is introduced, assuming that
ECS = []
An array represents the execution context stack. That is, the javascript engine pushes the globalContext into the ECS stack when executing global code, and then pushes the function execution context into the ECS when it encounters a function. When the function completes, Then pop the corresponding execution context from the ECS
The javascript engine manages various execution contexts through the execution context stack
There are three important properties in the execution context:
-
Variable Object (VO)
-
this
-
Scoped chain (scoped chain)
Variable Object + all Parents scopes — private scopes that contain variable objects and all parent maintenance ([[scope]])
Each execution context assigns a variable object, whose properties consist of a variable declaration and a function declaration. In the context of function execution, the variable object also includes the argument.
In the context of function execution, there is also the concept of an activation object (AO).
When the function is activated, an activation object is created and assigned to the execution context. The active object is initialized from the special object Arguments. It is then used as a variable object for variable initialization
That is, in the context of functions:
variableObject = activationObject + variableObject
Here’s an example:
function test(num){
var a = "2";
return a+num;
}
Copy the code
In the context of the test function above, the variable object contains not only the variable A, but also the parameter num. In short, you can think of the variable object and the active object as the same thing, except that the variable object of the function also has a parameter. (This is not correct, but can be used to memorize simple -)
About scope chains: When each function is created, a [[scope]] property is maintained inside the function
Here’s an example:
function foo() {
function bar() {... }}Copy the code
When a function is created, its respective [[scope]] is:
foo.[[scope]] = [
globalContext.VO
];
bar.[[scope]] = [
fooContext.AO,
globalContext.VO
];
Copy the code
This may not be intuitive: here’s another example:
Finally, a classic question (simplified) :
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope()
Copy the code
What is the output up here? What is the specific implementation process?
-
ContextStack = [globalContext] contextStack = [globalContext]
-
Global context initialization,
globalContext={
variable object:[scope, checkscope],
scope chain: variable object // Global scope chain
}
Copy the code
Checkscope.[[Scope]] = GlobalContext.scopechain
-
Checkscope =[checkscopeContext, globalContext]; checkScope =[checkscopeContext, globalContext]; The checkScope context is then initialized, which copies the [[Scope]] variable build Scope of the checkScope function, checkscopeContext={scopeChain: [checkScope.[[Scope]]]}
-
Checkscope event object is created The checkscope. ActivationObject = [the arguments], then the active object is used to initialize object being as a variable, Checkscope. VariableObject = checkscope. ActivationObject = [the arguments, the scope, f], then the variable object by the checkscope scope chain front end, (checckscope.scopeChain = [checkscope.variableObject, checkscope.[[Scope]] ]) == [[arguments, scope, f], globalContext.scopeChain]
-
Function f is initialized, f.[[Scope]] = checkScope.scopechain.
-
The checkScope execution stream continues down to return f(), which enters the function f execution context. Function f’s execution context is pushed into the stack, contextStack = [fContext, checkscopeContext, globalContext]. Function f repeats step 4. Finally f.s copeChain = [f.v ariableObject, checkscope scopeChain]
-
ContextStack = [checkscopeContext, globalContext]; contextStack = [checkscopeContext, globalContext]; ScopeChain (local scope); scopeChain (local scope); scopeChain (local scope);
-
ContextStack = [globalContext]
The above is my understanding of javascript execution context and scope, and many places are not precise. If you need to dig deeper, I suggest reading the following reference article
Reference article:
A JS interview questions triggered by the thinking
JavaScript deep scope chain
JavaScript deep execution context stack
JavaScript deep variable objects
JavaScript deep lexical scope and dynamic scope