hoisting 是在javascript執行時的一個行為

javascript會在編譯的過程先將所有宣告(declarations)的變數做reference

用下面的例子解釋

1
2
3
4
5
6
a;
b;
var a = b;
var b = 2;
b;
a;

而hoisting則會讓執行的結果變成

1
2
3
4
5
6
7
8
var a;
var b;
a;
b;
a = b;
b = 2;
b;
a;

在執行的時候就會產生上述的結果

而在function也會有同樣的行為

1
2
3
4
5
6
7
8
9
10
11
12
var a = b();
var c = d(); // d is not a function
a;
c;
function b() {
return c;
}
var d = function() { // function expression
return b();
}

這裡 hoisting則會讓執行的結果變成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function b() {
return c;
}
var a;
var c;
var d;
a = b();
c = d(); // d is not a function
a;
c;
d = function() {
return b();
}

重複的 hoisting 會將前面的宣告覆蓋過去

1
2
3
4
5
6
7
8
9
10
11
foo(); // "foo"
var foo = 2;
function foo() {
console.log("bar");
}
function foo() {
console.log("foo");
}

Hoisting 在做 mutual recursion 的時候非常重要

若沒有hoisting的話

永遠都會有一個function太晚宣告而無法正確執行程式

而hosting 讓下面的程式可以執行

1
2
3
4
5
6
7
8
9
10
11
12
a(1); // 39
function a(foo) {
if (foo > 20) return foo;
return b(foo+2);
}
function b(foo) {
return c(foo) + 1;
}
function c(foo) {
return a(foo*2);
}

用 let 宣告的變數不會進行hoisting

1
2
3
4
5
6
7
8
function foo(bar) {
if (bar) {
console.log(baz);
let baz = bar;
}
}
foo("bar");

Ref:

frontendmasters advanced-javascript

You-Dont-Know-JS