JavaScript - Closure與Hoisting
分散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 Scoping and Hoisting - 清楚說明Scope、Hoisting、Function的相關觀念
- Functions: declarations and expressions - 承上,Function相關可參考這篇文章
- JavaScript Patterns - 「Hoisting:分散var造成的問題」
- Closures - Access to outer variables, nested functions and closures.
- Initialization of functions and variables - 對JavaScript這個語言特性有興趣的可以參考這篇文章,將Lexical Environment和Pre-processing Stage的流程和所做的事情解釋得很清楚。
- [筆記] JavaScript 變數宣告與作用域 - 不要以為自己遇不到噢!前輩說他遇到了...
由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-JavaScript: Closure 與 Hoisting。
留言