標籤:
<script>
function f1()
{
var age = 18;
function f2()
{
alert(‘我今年:‘+age+‘歲‘);
}
return f2;
}
var func3 = f1();
func3();
</script>
閉包原理詳解:----->JS的執行原理
首先,js執行分為兩步驟,先行編譯階段和執行階段,明白了這個步驟,那麼就以上述例子為例來慢慢分析(先花一點時間,看看上述代碼,自己理解一下,再看下面的說明,效果更佳)
注:當我們在瀏覽器訪問這個頁面時,瀏覽器已經在瞬間完成了先行編譯和執行階段
** 函數在聲明時,會建立一個與之關聯的使用中的物件(Active Object)也叫AO對象,AO裡麵包括很多東西,除了函數執行環境內的變數和函數的資訊,還包括arguments對 象,scope屬性,this對象等.
1. 先行編譯階段:
1.1 在全域層面建立VO對象,vo對象包含全句的變數聲明和函數,
虛擬碼: VO={ f1:function(){.....}}
1.2 進入函數f1 ,建立AO對象(AO對象和VO對象的角色一樣,只是叫法不一樣)
1.2.1 首先分析形參,函數沒有形參,
1.2.2 再分析變數聲明 有,AO{‘age‘:‘undefined‘}
1.2.3 再分析函式宣告 有,AO{‘f2‘:‘function(){..}‘}
此時整個VO對象為:
VO和AO(使用中的物件)角色一樣,只是叫法不一樣,不用死扣.
VO{
f1:function()
{AO
‘age‘:‘undefined‘
‘f2‘:‘function()
{AO
scope:指向f1的AO對象 ###每個函數被聲明時,都會建立一個與之關聯的scope的屬性
##scope總是指向定義函數時所在的環境
}‘ ##就因為有了scope,範圍鏈的效果才能體現出來,所以scope很偉大
scope:指向VO
}
}
2.執行階段
2.1 f1(),執行,f1執行環境的AO對象:AO{‘age‘:18};
f2內的AO{‘age‘:18,scope:指向f1的執行環境}
2.2 func3(),執行,實際是在執行:f2(),而f2的AO{‘age‘:18,scope:指向f1的執行環境,alert(‘我今年:‘+age+‘歲‘)}
所以func3() 能接受到局部變數age 因此就能列印出18.
注:考慮到能更簡單/易懂瞭解到閉包,所以上述代碼在執行細節和執行情況做了簡化,沒有牽扯到太晦澀難懂的知識點(環境棧等),若想瞭解JS更進階的部分,推薦<Javascript權威指南>
如果有朋友還是不太懂閉包,js執行原理,可以留言,一起探討.
通過一個簡單閉包,弄懂JS執行原理