JavaScript: Closure 與 Hoisting

JavaScript

分散 var 來宣告變數並沒有太大的意義,因為就 JavaScript 程式語言的特性來說,函數(Function)中未宣告而先用到的變數會被提升至區塊的第一行做宣告。先來看基本觀念 Closure,再來看 Hoisting。

Closure

Closure 是指變數的生命週期只存在於該 Function 中,一旦離開了 Function,該變數就會被回收而不可再利用,且必須在 Function 內事先宣告。

function closure() {
  var a = 1;
  console.log(a); //1
}
closure();
console.log(a); //Uncaught ReferenceError: a is not defined

對於 Closure 進一步的探討可參考這篇文章 Closures

Hoisting

Hoisting 是一種把宣告提升到其所在區域內頂端的行為,意即程式會將 Function 中全部需要宣告的 Local Variable,提升到 Function 的第一行來執行,但不包含初始值設定。

var a = 1;
function hoisting() {
  if (!a) {
    var a = 999;
  }
  console.log(a); //999
}
hoisting();

咦!?怎麼會是 999 呢?a 在第一行已初始化為 1,必不為 0、undefined、空字串或 null,怎麼會造成判斷!a === true呢?原來對於 JavaScript 來說,所有未宣告的 Local Variable 都會被提到第一行做宣告(但不設定初始值,即初始值為 undefined),意即:

var a = 1;
function hoisting() {
  var a = undefined;
  if (!a) {
    a = 999;
  }
  console.log(a); //999
}
hoisting();

會有 Hoising 這樣的狀況當然和 JavaScript 語言本身的特性有關,即在執行程式前會有「Variables Instantiation」的動作 - 將使用 var 的變數宣告先辨識起來(除了 Function 外,初始值設為 undefined),到了執行階段才給予初始值。相關可參考這篇文章 Initialization of functions and variables

推薦閱讀


這篇文章的原始位置在這裡-JavaScript - Closure 與 Hoisting

由於部落格搬遷至此,因此在這裡放了一份,以便閱讀;部份文章片段也做了些許修改,以期提供更好的內容。

javascript closure 閉包 ReferenceError undefined javascript