Hoist
Vt. Arise, lift;
VI. be lifted or elevated;
N. cranes, lifts; Rises < slang > Push, hold, lift;
This article does not speak English, but for some English words can not find a good translation, the first to list the word "hoist" is to let everyone have a preparation, I am here to translate the word "in advance", is to explain the JavaScript language is a "strange" feature.
Variable declaration "was advanced"
The syntax of JavaScript is similar to C, Java, C #, and is collectively referred to as Class C syntax. Students with C or Java programming experience should be familiar with the "declare first, later use" rule, and if you use an undeclared variable or function, you will get an error during the compile phase. However, JavaScript is able to use them before variables and functions are declared. Let's take a closer look at the mystery.
Take a look at the code first:
(function() { //ReferenceError: noSuchVariable is not defined console.log(noSuchVariable);})();
Running the above code immediately error, but this is what we expect, because the noSuchVariable
variable is not defined at all! Then take a look at the following code:
(function() { // Outputs: undefined console.log(declaredLater); var declaredLater = "Now it‘s defined!"; // Outputs: "Now it‘s defined!" console.log(declaredLater);})();
First of all, the above code is correct and there is no problem. But, why not the error? declaredLater
is the variable defined after the call statement? Why does it actually output undefined
?
This is actually a JavaScript parser, the parser will put all the variables and functions declared in the current scope at the beginning of the scope, but only the declaration of the variable is advanced to the beginning of the scope, and the assignment operation is left in place. The code above for the parser actually looks like this:
(function() { var declaredLater; //声明被提前到作用域开始处了! // Outputs: undefined console.log(declaredLater); declaredLater = "Now it‘s defined!"; //赋值操作还在原地! // Outputs: "Now it‘s defined!" console.log(declaredLater);})();
This is why the above code does not report the reason for the exception! After the variables and functions have been "advanced", the declaredLater
variables are actually placed in front of the calling function, and variables that have been declared and not assigned are automatically assigned as defined by the JavaScript syntax, undefined
so the value of the first print declaredLater
variable is undefined
The c4/> variable is assigned, so the second re-print variable is output Now it‘s defined!
.
Let's look at one more example:
var name = "Baggins";(function () { // Outputs: "Original name was undefined" console.log("Original name was " + name); var name = "Underhill"; // Outputs: "New name is Underhill" console.log("New name is " + name);})();
In the above code, we first declare a variable name
, we want to be able to print the variable at the first time name
to output the global scope of the name
variables defined, and then define a local variable in the function name
overrides the global variable, and finally output the value of the local variable. The result of the first output, however, is completely inconsistent with our expectations, because the local variables we define are "ahead" in their scope, that is, they become the following form:
var name = "Baggins";(function () { var name; //注意:name 变量被提前了! // Outputs: "Original name was undefined" console.log("Original name was " + name); name = "Underhill"; // Outputs: "New name is Underhill" console.log("New name is " + name);})();
Because JavaScript has this "quirks", you'll see that many coding guidelines suggest that you put variable declarations at the top of the scope so you can always remind yourself.
function declaration "Advanced"
The front is about variables, and then we're talking about functions.
The function is "advanced" in two cases, one is a function declaration, the second is a function as a value assigned to the variable.
First of all, on the code:
// Outputs: "Yes!"isItHoisted();function isItHoisted() { console.log("Yes!");}
As shown above, the JAVASCRIPT interpreter allows you to use before the function declaration, that is, the function declaration is not just the function name "is advanced", the definition of the entire function is "advanced"! So the above code can be executed correctly.
Consider the second case: The function is assigned as a value to the variable. (Do you remember?) In JavaScript, a function can also be given a variable as a value! ) or the code first:
// Outputs: "Definition hoisted!"definitionHoisted();// TypeError: undefined is not a functiondefinitionNotHoisted();function definitionHoisted() { console.log("Definition hoisted!");}var definitionNotHoisted = function () { console.log("Definition not hoisted!");};
We make a comparison, the definitionHoisted
function is executed properly, conforms to the first type, the definitionNotHoisted
variable is "advanced", but his assignment (that is, the function) is not advanced, and from this point, the variable we said earlier is "in advance" is exactly the same, and, because "is advanced" The default value of the variable is undefined
, so the reported error belongs to "Type mismatch" because it undefined
is not a function and of course cannot be called.
Summarize
The above explanation can be summarized as follows:
- The declaration of a variable is advanced to the top of the scope, and the assignment remains in place
- function declaration the entire "being ahead"
- When a function is assigned to a variable as a value, only the variable is "advanced" and the function is not "advanced"
Feel more about yourself by practicing the above examples. Also, as a best practice: variable declarations must be placed at the top of the scope/function (JavaScript has only function scopes!). )。
"Advance (hoist)" For variables and function declarations in JavaScript