Get into the habit of writing together! This is the 11th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .
This article was first published on my blog .
1 Introduction
The JS engine will precompile before executing JavaScript. During JS precompilation, var
variable declarations and function
function declarations in JS will be advanced to the front of the current scope.
Traditional arts, let's first look at a question to see if you have fully grasped the declaration promotion: what
is the correct output of the following code? (The answer is the best, if you are not very clear, it is recommended to continue reading.)
var foo = function () {
console.log(100);
}
function foo() {
console.log(200);
}
foo();
复制代码
2. Declarative boost
Before the JS engine interprets and runs the code, it will first process all declarations in any code, including variables and functions, and put them at the forefront of the current scope, while the remaining assignment statements stay in place and wait for execution. The declaration is brought forward from the original position to the front of the current scope, so it is called declaration hoisting (Hoisting) .
2.1 Variable declaration hoisting
// 输出 undefined
console.log(a);
var a = 'hello';
复制代码
According to variable promotion, the variable is declared a
through var
, this declaration var a
will be advanced, and the variable a = 'hello'
will stay in place. So the code is equivalent to:
var a;
// 输出 undefined
console.log(a);
a = 'hello';
复制代码
Note that variable declarations are hoisted, but variable initializations are not.
// 输出 undefined
console.log(a);
var a;
a = 'hello';
复制代码
Every scope in the code is hoisted.
console.log(a); // undefined
var a = 100;
function fn() {
console.log(b); // undefined
var b = 200;
function gn() {
console.log(c); // undefined
var c = 300;
}
gn();
}
fn();
复制代码
The output of the above code, after being boosted, is equivalent to:
var a;
console.log(a); // undefined
a = 100;
function fn() {
var b;
console.log(b); // undefined
b = 200;
function gn() {
var c;
console.log(c); // undefined
c = 300;
}
gn();
}
fn();
复制代码
2.2 Function declaration hoisting
function
Declaring a function also has the declaration hoisting feature, and the function declaration (including the function body) is brought to the front of the current scope.
// 输出 hello
foo();
function foo() {
console.log('hello');
}
复制代码
The above code is equivalent to:
function foo() {
console.log('hello');
}
// 输出 hello
foo();
复制代码
Note that var
declared function expressions do not have function declaration hoisting. For example the following anonymous function expression:
// 输出 undefined
console.log(foo);
foo(); //TypeError: foo is not a function
var foo = function () {
console.log('hello');
}
复制代码
The above code is equivalent to:
var foo;
console.log(foo); // 输出 undefined
foo(); // TypeError: foo is not a function
foo = function () {
console.log('hello');
};
复制代码
For named function expressions, there is also no declaration of hoisting.
console.log(foo); // undefined
foo(); // TypeError: foo is not a function
var foo = function bar() {
console.log('hello');
}
复制代码
Note: The name of a named function expression can only be used inside the function, not outside the function.
var bar = 10;
var foo = function bar() {
bar = 30; // (3)
console.log(bar); // (1)
}
foo();
console.log(bar); // (2)
bar(); // (4)
复制代码
In the above code, (1) outputs:
ƒ bar() {
bar = 32;
console.log(bar);
}
复制代码
Output at (2): 10
, the code at (3) is invalid, and an error is reported at (4).
The
let
andconst
do not have the declaration hoisting feature.
3. Function declaration takes precedence
If there are declarations of variables and functions with the same name in the code, both will be promoted, and finally the function declaration will override the variable declaration.
// 输出:foo () {}
console.log(foo);
var foo = 100;
function foo () {}
复制代码
The above code is equivalent to:
function foo() {};
var foo; // 变量提升被函数声明提升覆盖,变量重复声明无效
console.log(foo); // foo() {}
foo = 100;
复制代码
But if there is an assignment statement console.log
before , it foo
is the value of the variable.
var foo = 100;
function foo () {};
console.log(foo); // 100
复制代码
Note that repeated declarations of variables are useless, but repeated declarations of functions override previous declarations .
- Repeated declarations of variables are useless
var foo = 100; var foo; console.log(foo); // 100 复制代码
- Duplicate declarations of functions overwrite previous declarations
foo(); // 200 function foo () { console.log(100); } function foo () { console.log(200); } 复制代码
- Function declaration hoisting takes precedence over variable declaration hoisting
The above code is equivalent to:foo(); // 200 var foo = 100; function foo() { console.log(200); } 复制代码
function foo() { console.log(200); } var foo; foo(); // 200,函数声明提升优先于变量声明提升,变量声明无效 foo = 100; 复制代码
4. Some cases
Case 1:
var bar = 100;
function foo () {
console.log(bar); // (1)
var bar = 200;
console.log(bar); // (2)
}
复制代码
will output at (1) and output undefined
at (2) 200
. According to the variable promotion principle, the above code is equivalent to:
var bar = 100;
function foo () {
var bar;
console.log(bar); // undefined
bar = 200;
console.log(bar); // 200
}
复制代码
Case 2:
var foo = function () {
console.log(100);
}
function foo() {
console.log(200);
}
foo();
复制代码
The above code will output 100
, according to the function declaration promotion priority principle , the code can be converted to:
function foo() {
console.log(200);
}
var foo;
foo = function () {
console.log(100);
} // 原函数被变量赋值覆盖,此时 foo 函数体为后面赋值的。
foo(); // 100
复制代码