JavaScript hoisting

重新複習一下 JavaScript 一些奇怪的機制,例如 hoisting,很多面試題目照著直覺下去寫答案往往都沒有跟想像中一樣簡單,所以就來重新了解一下 hoisting 機制。

JavaScript hoisting
Photo by Lindsay Henwood / Unsplash

重新複習一下 JavaScript 一些奇怪的機制,例如 hoisting,很多面試題目照著直覺下去寫答案往往都沒有跟想像中一樣簡單,所以就來重新了解一下 hoisting 機制。

範例

面試題目都大概會長得這樣

console.log(foo)
var foo = 10

會得到 undefined 那麼用 hoisting 的角度來看應該是這樣的

var foo
console.log(foo)
foo = 10

function foo(bar) {
  console.log(bar)
  var bar = 1
}
foo(5)

這題答案是 5 讓我們拆解一下:

function foo(bar) {
  var bar = 5
  var bar
  console.log(bar)
  bar = 1
}
foo(5)

那麼這樣不是應該會得到 undefined 嗎?,讓我們先看一下這個範例

var foo = 5
var foo
console.log(foo)

// 其實會等於
var foo
var foo
foo = 5
console.log(foo) // 5

所以最後整個方法在 hoisting 角度看來就會是

function foo(bar) {
  var bar 
  var bar
  bar = 5
  console.log(bar)
  bar = 1
}
foo(5)

接者看一下混著全域變數在裡面的題目,例如:

var a = 1
function foo() {
  if(!a) {
    var a = 5
  }
  console.log(a)
}
foo()

如果看過上一題範例知道 hoisting 可以推論出答案是 5
原因如下:

var a = 1
function foo() {
  var a // undefined
  if(!a) { // !undefined = true
    a = 5
  }
  console.log(a)
}
foo()

最後來點不一樣的:

console.log(foo)
var foo
function foo() {}

想一下一定沒有這麼簡單!答案會是 ƒ foo() {}
function 的宣告也會提升,而且權重會比變數來得高。所以會得到 ƒ foo() {}

知識點

  • hoisting 機制會把宣告給「提升至區域的頂端」可是不會把賦值也一起提升。
  • 宣告 function 也會提升
  • 變數內的傳值也是會被 hoisting