var
a = 1;
function
foo() {
if
(!a) {
var
a = 10;
}
alert(a);
};
foo();
What is the result of the above code when it is run?
Beginner ideas:
1. The global variable a is created and its value is defined as 1
2. The function foo is created
3. In the function body of foo, the if statement will not be executed, because !a will convert the variable a into a boolean false value, which is false
4. Skip the conditional branch, alert variable a, the final result should be output 1, but the correct answer is 10.
Why 10? This is due to variable hoisting:
Declaration and Definition
To understand variable hoisting , let's first look at a simple case:
var a = 1;
the following example is called "declaring a variable":
var a;
The following example is called "defining a variable":
var a = 1;
Declaration: means that you claim the existence of something, such as a variable or a function; but you do not say what such a thing is, just tell the interpreter that such a thing exists;
Definition: means that you specify something The specific implementation, such as what is the value of a variable, what is the function body of a function, exactly expresses the meaning of such things.
in conclusion:
var a; // this is the declaration
a = 1; // this is the definition (assignment)
var a = 1; // two in one: declare the existence of the variable and assign to it
Here comes the point: when you think you only do one thing (var a = 1), the interpreter actually breaks it down into two steps, one is the declaration (var a) and the other is the definition (a = 1).
How does this relate to variable hoisting?
Going back to that confusing example at the beginning, I tell you how the interpreter analyzes your code:
Scope:
One might ask: "Why not declare the variable a inside the if statement?"
Because JavaScript does not have block-level scope, only function scope (Function Scoping), so if you don't see a pair of curly braces {}, it means that a new scope is generated, which is different from C!
When the parser reads the if statement, it sees that there is a variable declaration and assignment, so the parser hoists its declaration to the top of the current scope (this is the default behavior and cannot be changed), this behavior is called Variable promotion.
What if I just want alert(a) to output that 1?
Create new scope
When alert(a) is executed, it will look for the location of the variable a. It starts from the current scope (or outwards) until it reaches the top-level scope. If it is not found, it will report undefined.
Because in the sibling scope of alert(a), we declare the local variable a again, so it reports 10; so we can move the declaration of the local variable a down (or inward), so that alert(a) just can't find it.
Remember: JavaScript only has function scope!
1. Language-defined naming: such as this or arguments, they are valid in all scopes and have the highest priority, so you cannot name variables like this anywhere, which is meaningless
2. Formal parameters: Formal parameters declared when a function is defined are hoisted into the function's scope as variables. So the formal parameters are local, not external or global. Of course, you can pass in external variables when executing the function, but after passing in, it is local
3. Function declaration: Functions can also be declared inside the function body, but they are also local
4. Variable declaration: This takes precedence The level is actually still the lowest, but they are also the most commonly used
Further understanding of the difference between declaration and definition: hoisting only promotes the name, not the definition
Difference between function declaration and function expression
Let's look at two examples:
In the first example, the function foo is a declaration, and since it is a declaration, it will be hoisted (I deliberately wrapped an outer scope, because the global scope requires your imagination, not so intuitive, but the principle is the same) , so the scope knows about the existence of function foo before foo() is executed. This is called a function declaration, and the function declaration is hoisted to the top of the scope along with the name and the function body.
In the second example, only the variable name foo is hoisted, and its definition remains in place. Therefore, before executing foo(), the scope only knows the name of foo, not what it is, so the execution will report an error (usually: undefined is not a function). This is called a function expression, and only the name of the function expression will be hoisted, the body of the defined function will not.