Home > Article > Web Front-end > In-depth understanding of scope and variable hoisting in JS
Scoping
For Javascript beginners, one of the most confusing things is scope; in fact, it’s not just beginners. I have met some experienced JavaScript programmers, but they do not understand scope deeply. The reason why JavaScript scope is confusing is that its program syntax itself looks like the C family of languages. My understanding of scope is a closed space that only affects a certain range and does not affect the outside world. In some such spaces, internal variables cannot be accessed from the outside, but external variables can be accessed from the inside.
Variables in C language are divided into global variables and local variables. The scope of global variables is accessed by any file and function (of course, for other C files defined by non-variables, you need to use the extern keyword for declaration, and the static keyword can also be used. You can limit the scope to the current file), and the scope of a local variable is the block-level scope from the declaration to the nearest curly brace. Java does not have global variables, but has class variables, member variables and local variables. The scope of scope has different scopes according to public, protected, private and other access rights. I will not go into details here.
What are the scopes of JS?
In ES5, js has only two forms of scope: global scope and function scope.
The global scope is actually the scope of the global object, which can be accessed anywhere (if it is not covered by the function scope).
The function object scope is different from the local variable scope of c. Its scope is the entire function scope, regardless of whether it is declared anywhere in the function! This is called hoisting, which is the concept of variable hoisting. But don’t worry, I will explain hoisting specifically below.
However, in ES6, there is a new block-level scope (the scope covered by the recent curly braces), but it is limited to variables declared in the let method.
Scope demonstration:
When defining a variable, if you do not write var, such as i=0, it will be defined as a global variable and the scope is the global scope. Otherwise, it is a local variable and the scope is the function. Scope. The var i=0 in the first line above is said to be a global variable because it has been declared in the global area and is not within the scope of the function, so it is the same as i=0.
As for why the result is like this, you will know by reading on.
Declaration form
Variable declaration:
Function declaration:
Variable Hoisting (Hoisting)
leads to a question
What will the following code output?
I have interviewed many people for this question, and most of them said that the output is the date. But the real result is undefined. Why is this? Here comes a concept - hoisting, which means variable hoisting in Chinese. The explanation of variable hoisting in MDN is this:
var hoisting
Because variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it's declared. This behavior is called "hoisting", as it appears that the variable declaration is moved to the top of the function or global code.
This passage is translated That’s because variable declaration is processed before any code is executed. Declaring a variable anywhere in the code area is the same as declaring it at the very beginning (top). That is, it looks like a variable can be used before it is declared! This behavior is called "hoisting", that is, variable hoisting, which looks like the declaration of the variable is automatically moved to the top of the function or global code.
Note: Only the declaration is upgraded, the definition will not be upgraded.
So, the above code is actually in the following form:
So, it should be understood that when the console outputs, the tmp variable is only declared but not defined, so the output should be undefined.
What needs to be noted here is that although all declarations (including ES5's var, function, and ES6's function *, let, const, class) will be promoted, var, function, function * and let, const, class Improvement is not the same! The specific reasons can be found here (the general meaning is that although let, const, and class are also promoted, they will not be initialized. If you access them at this time, a ReferenceError exception will be reported. They need to wait until the statement is executed. will be initialized, and the state before initialization is called temporal dead zone). Let’s look at a piece of code to find out:
Here a is promoted, but because it is defined later, the output is undefined
Although a is promoted here, a reference error is reported!
The reason why is this
For this reason, the recommended approach is to write all the variables at the top of the scope (global scope or function scope) when declaring variables, so that the code looks like It will be clearer, and it will be easier to see which variable comes from the function scope and which one comes from the scope chain (this article will not explain more about this, please read it on your own and add more explanations when you have the opportunity).
Repeat statement
The above output is actually: 1 2 2. Although it seems that x is declared twice, as mentioned above, there are only two types of var variables in js: global scope and function scope, and the declaration will be promoted, so in fact x will only be declared at the top. Once, the declaration of var x=2 will be ignored and only used for assignment. In other words, the above code is actually consistent with the following.
The problem of simultaneous promotion of functions and variables
What will happen if the function and variable types are declared at the same time? Look at the code below
The above output is actually: function foo(){}, which is the function content.
And what if it is in this form
The output becomes: undefined
Why is this?
It turns out that function promotion is divided into two situations:
. It’s the form A above, function foo(){}
and another: function expression. It is the form B above, var foo=function(){}
The second form is actually the declaration definition of the var variable, so it should be understandable that the output result of B above is undefined.
The first form of function declaration will be completely upgraded during promotion, including the function definition part! Therefore A is equivalent to the following method!
The reason is because: 1. The function declaration is promoted to the top; 2. The declaration is only made once, so the subsequent declaration of var foo='i am text' will be ignored.
And function declarations have priority over variable declarations, so the output in the following form is also the function content:
Summary
To fully understand the scope and Hoisting of JS, just remember the following three points: Can:
1. All declarations will be promoted to the top of the scope 2. The same variable declaration is only made once, and therefore other declarations will be ignored 3. Function declarations have priority over variable declarations , and the function declaration will be promoted together with the definition
Note:
The scope chain of the runtime context can be temporarily changed through the with statement. At this time, when accessing non-var-defined variables, the object in with will be accessed first. property, and then the property is checked up the scope chain.