In-depth understanding of the lexical and dynamic scopes of the second part of javascript scopes, and javascript lexical
Previous
Most of the time, the main cause of confusion on the scope is that it is unclear whether to search for variables based on the nested order of the function location or the call sequence of the function. Coupled with the interference of this mechanism, variable search is prone to errors. This is actually caused by two scope working models. The scopes are divided into lexical scopes and dynamic scopes. The two scope models can clearly understand the variable search process. This article is the second part of the javascript scope series-lexical scope and dynamic scope
Lexical Scope
As described in the first article, the first phase of the compiler is called word segmentation, which is to break down character strings into lexical units. This concept is the basis for understanding the lexical scope.
Simply put, the lexical scope is the scope defined in the lexical stage. It is determined by where variables and block scopes are written during code writing, therefore, when the lexical analyzer processes code, the scope remains unchanged.
Link
No matter where a function is called or how it is called, its lexical scope is determined only by the position where the function is declared.
function foo(a) {var b = a * 2;function bar(c) {console.log( a, b, c );}bar(b * 3);}foo( 2 ); // 2 4 12
In this example, there are three step-by-step nested scopes. To help you understand them, you can think of them as several bubbles that are contained step by step.
The scope bubble is determined by where the corresponding scope block code is written. They are contained step by step.
Bubble 1 contains the entire global scope, with only one identifier: foo
Bubble 2 contains the scope created by foo, which has three identifiers: a, bar, and B.
Bubble 3 contains the scope created by bar, with only one identifier: c
Search
The structure of the scope bubble and the positional relationship between each other provide sufficient location information for the engine to find the location of the identifier.
In the code snippet, the engine executes the console. log (...) Declaration and searches for references to three variables a, B, and c. It first searches for the most internal scope, that is, the scope of the bar (...) function. The engine cannot find a here, so it will go to the scope of the last level to the nested foo (...) to continue searching. A is found here, so the engine uses this reference. The same applies to B. For c, the engine finds it in bar (...).
[Note] only the first-level identifiers will be searched for in the lexical scope. If the code references foo. bar. baz, the lexical scope lookup will only try to find the foo identifier. After finding this variable, the object attribute access rules take over access to the bar and baz attributes respectively.
foo = {bar:{baz: 1}};console.log(foo.bar.baz);//1
Masking
Scope lookup starts from the most internal scope of the runtime, and goes outward or upwards step by step until the first matching identifier is met.
You can define identifiers with the same name in multi-layer nested scopes. This is called "masking effect". Internal identifiers "mask" external identifiers.
var a = 0;function test(){var a = 1;console.log(a);//1}test();
The global variable is automatically the attribute of the global object. Therefore, you can access the Global Object Attributes indirectly instead of using the lexical name of the global object.
var a = 0;function test(){var a = 1;console.log(window.a);//0}test();
With this technology, you can access global variables that are masked by variables with the same name. However, if non-global variables are masked, they cannot be accessed in any way.
Dynamic Scope
Javascript uses lexical scopes. Its most important feature is that its definition process occurs in the code writing stage.
Why do we introduce dynamic scopes? In fact, dynamic scopes are the cousin of another important mechanism of javascript, this. Most of the scope confusion is caused by confusion between the lexical scope and the this mechanism.
Dynamic scopes do not care about how functions and scopes are declared and where they are declared. They only care about where they are called. In other words, the scope chain is based on the call stack, rather than the scope nesting in the code.
var a = 2;function foo() {console.log( a );}function bar() {var a = 3;foo();}bar();
[1] if it is in the lexical scope, that is, the current javascript environment. Variable a is first searched in the foo () function and cannot be found. Then, search for the global scope along the scope chain, find and assign the value to 2. Therefore, the console outputs 2
[2] if it is in a dynamic scope, similarly, variable a is first searched in foo () and cannot be found. Here, the call stack is searched in the place where the foo () function is called, that is, the bar () function, and the value is 3. Therefore, the console outputs 3
Summary: the differences between the two scopes. In short, the lexical scopes are defined, while the dynamic scopes are determined at runtime.
The above section describes the lexical and dynamic scopes of the second article of javascript scopes. I hope this article will help you. If you want to learn more, please stay tuned to the help house!