JS 中的變數提升 Hoisting 是什麼

什麼是 Hoisting?

Hoisting 就是「提升」的意思。

1
2
console.log(i)
//Uncaught ReferenceError: i is not defined

舉例來說,當只有console.log時,就會出現 not defined,因為我們試圖去對一個還沒被宣告的變數取值,才會出現此錯誤。

1
2
3
console.log(i)
var i
//undefined

上面的例子中,是在下方 ( 第二行 ) 宣告變數時,會出現 undefined,此現象就叫做Hoisting

不同於以往我們對程式的認知為一行一行跑,第二行的var i,因為某些原因,被提升到了最上面。

1
2
3
console.log(i)
var i = 5
//undefined

但是變數提升,只會提升變數的宣告會提升。賦與的值( 賦值 )並不會被提升。依然會是 undefined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// PART 1
function test(i){
console.log(i);
var i;
}
test(10)
// 10

// PART2
function test(i){
var i = 10;
console.log(i);
var i;
}
test(10)

當以 function 宣告的時候,會出現10,而不是 undefined

因為值會是以 PART2 的樣子,出現在 Function 的第一行,就被宣告且賦值了!

最後,functoin 的宣告也會提升而且優先權較高,所以程式會輸出function而不是undefined

1
2
3
4
console.log(a)
var a
function a(){}
// [Functoin: a]

let const var 與 hoisting

letconst 的作用域

let const var 最主要的差異是:ES6 letconst 以「區塊」作為其作用域 ( scope )。而 var 以「函數」作為其作用域。

letconst 換句話說,就是只有在區域裡面才看的到。以下方的例子來說。

1
2
3
4
5
{
let name = "Phoebe";
console.log(name); // Phoebe
}
console.log(name); // undefined

name 這個變數只有在大括號裡,也就是區域內才看的到。

var的作用域

var 的作用域是函式作用域 ( function-level scope )。

換句話說就是,用 var 宣告的變數,只有在「函式」裡可以看得到。

為什麼我們需要 hoisting 呢?

可以從反向思考,「如果沒有 hoisting 會怎麼樣?」

  1. 一定要宣告變數才可以使用 (其他語言的習慣)
  2. 一定要宣告函式才可以用 (特別注意)
  3. 沒有辦法達成 function 互相呼叫

舉個例子

1
2
3
4
5
6
7
8
9
10
11
function loop(n){
if (n>1) {
show(--n)
}
}

function show(n) {
console.log(n, n % 2 ? '奇數' : '偶數')
loop(n)
}
loop(20)

我們在 loop 裡面呼叫 show(),在 show() 裡面也呼叫 loop(),如果沒有 hoisting ,以上程式碼就不會達成。

因為,不可能做到 A 在 B 上面,而 B 又在 A 上面。

所以 hoisting 就是為了解決上述的問題 !

參考文章

我知道你懂 hoisting,可是你了解到多深?

[教學] JavaScript 中的 Hoisting 是什麼意思?let const var 的差異居然是這個? | Shubo 的程式教學筆記


JS 中的變數提升 Hoisting 是什麼
https://phoebeho.com/Javascript/20210413/1504964144/
作者
Phoebe
發布於
2021年4月13日
許可協議