What is the result of the following program?
What about the following one?
Shocking you? What happened? This may be strange, dangerous, and confusing, but it is also actually a very useful and impressive JavaScript language feature. I don't know if there is a standard name for this behavior, but I like this term: "Hoisting". This article will give an introductory explanation of this mechanism, but first let us have some necessary understanding of the scope of JavaScript.
Scope of Javascript
For Javascript beginners, one of the most confusing points 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 because the program syntax itself looks like a C family language, like the following C program:
For many C, c, java programmers, this is not what they expect and welcome. Fortunately, due to the flexibility of JavaScript functions, there are ways to work around this. If you must create a temporary scope, you can do it like this:
Variable declaration, naming, and promotion
In JavaScript, there are 4 basic ways for variables to enter scope:
•1 Language built-in: all scopes have this and arguments; (Translator's Note: After testing, arguments are not visible in the global scope)
•2 Formal parameters: The formal parameters of the function will be part of the scope of the function body;
•3 Function declaration: like this form: function foo(){};
•4 Variable declaration: like this: var foo;
Function declarations and variable declarations are always quietly "promoted" to the top of the method body by the interpreter. This means, like the following code:
The above covers some of the basics of boosting, and they don’t seem that confusing. However, in some special scenarios, there is still a certain degree of complexity.
Variable parsing order
The most important thing to keep in mind is the order of variable resolution. Remember the 4 ways that naming enters the scope I gave earlier? The order in which variables are parsed is the order I listed them.
<script></p>
<p>var a;<br>function a(){ <br>}<br>alert(a);//Print out the function body of a<br></script>
//But be careful Distinguish the difference from the following two writing methods:
<script><br>var a=1;<br>function a(){ <br>}<br>alert(a);//print out 1<br></script>
<script><br>function a(){ <br>}</p>
<p>var a=1;</p>
<p>alert(a);//print out 1<br></script>
1 The built-in name arguments behaves strangely. It seems that it should be declared after the function formal parameters, but before the function declaration. This means that if there are arguments in the formal parameter, it will have priority over the built-in one. This is a very bad feature, so avoid using arguments in formal parameters;
2 Defining this variable anywhere will cause a syntax error, which is a good feature;
3 If multiple formal parameters have the same name, the last one has priority, even if its value is undefined during actual operation;
Named function
You can give a function a name. If so, it is not a function declaration, and the specified function name (if any, such as spam below, translator's note) in the function body definition will not be promoted, but ignored. Here is some code to help you understand:
var foo = function () {}; // foo points to an anonymous function
function bar() {}; // Function declaration
var baz = function spam() {}; // Named function, Only baz is promoted, spam will not be promoted.
foo(); // valid
bar(); // valid
baz(); // valid
spam(); // ReferenceError "spam is not defined"
Now that you understand scoping and variable hoisting, what does this mean for JavaScript coding? The most important thing is to always define your variables with var. And I strongly recommend that for a name, there should always be only one var declaration in a scope. If you do this, you won't have scope and variable hoisting issues.
How to say language specification
I always find the ECMAScript reference documentation helpful. Here's what I found about scoping and variable hoisting:
If a variable is declared in a function body class, it is function scope. Otherwise, it is globally scoped (as a property of global). Variables will be created when execution enters scope. Blocks will not define new scopes, only function declarations and procedures (the translator thinks it is global code execution) will create new scopes. Variables are initialized to undefined when they are created. If there is an assignment operation in the variable declaration statement, the assignment operation will only occur when it is executed, not when it is created.
I hope this article will bring a ray of light to programmers who are confused about JavaScript. I also try my best to avoid causing more confusion. If I said something wrong or overlooked something, please let me know.
Translator’s supplement
A friend reminded me that I discovered the problem of improving named functions in the global scope under IE:
This is what I tested when I translated the article:
This question also led me to think about two other questions, 1: For variables that act globally on the scope, there is a difference between var and non-var. Without var, the variable will not be promoted. For example, of the following two programs, the second one will report an error: