js代碼在執行前會做的幾件事情: 1.代碼檢測 2.預編譯:在執行代碼之前會對代碼中的函數以及變數提前聲明 並且做一些其他的處理 1.函數在執行前的一瞬間,會生成一個OA(object action)對象 2.函數的形參作為OA對象的屬性名,實參作為AO對象的屬性值 3.分析var聲明,變數名作為A ...
js代碼在執行前會做的幾件事情:
1.代碼檢測
2.預編譯:在執行代碼之前會對代碼中的函數以及變數提前聲明 並且做一些其他的處理
1.函數在執行前的一瞬間,會生成一個OA(object action)對象
2.函數的形參作為OA對象的屬性名,實參作為AO對象的屬性值
3.分析var聲明,變數名作為AO對象的屬性名,值為undefined,如果遇到和參數同名的變數不去做任何改變
4.分析函數聲明,函數名作為AO 對象的屬性名,值為函數體,如果遇到同名函數直接覆蓋
接下來我們來分析這段代碼:(按照預編譯的四步走)
function fun(a){
console.log(a)
var a = 100
console.log(a)
}
fun(10)
1.在執行fun之前產生一個fun OA對象 ,
2.函數的形參a = 10 ,存入AO對象
3.var聲明瞭一個a 值為undefined
4.分析函數 這個函數裡面並沒有內層函數
做完以上分析之後 再來執行這個程式 執行過程中碰到變數的輸出或改變值 就去OA對象中找:
console.log(a) 此時a = 10 輸出10
a = 100 此時a=100
console.log(a) 輸出100
這是一個函數整體的執行過程,而閉包的形成就是在一個函數裡面嵌套一個或多個函數,接下來我們再來分析閉包
function a(){
var num = 100;
function b(){
num ++;
console.log(num)
}
return b;
}
var fun = a()
fun()
fun()
1.在a()執行前生成一個OA對象
2.沒有形參
3.聲明var num = undefined
3.聲明函數b() 值為函數體
然後執行a() 給num複製為100,然後返回b()函數 fun=function b(){ } 接下來在執行到fun()時:
1.在fun()執行前產生一個OA對象
2.沒有形參
3.沒有var聲明
4.沒有函數聲明
然後執行b()函數,此時num++,會先在b()自己的作用於內查找有沒有num這個變數 如果沒有沿著作用域鏈去查找num
找到a()中有num變數 這是對a()中的num執行++操作 所以a()中的num會發生改變 num=101
後續又執行了一次fun() 所有操作與上一個fun相同 但是此時a()中的num=101 再進行++操作後 num = 102
用圖像化來表示整個程式的執行過程中OA發生的變化
*在整個程式執行過程中 最最需要註意的是 函數每執行一次都會產生一個相應的OA對象
就算是同一個函數 只要再次執行都會產生一個對應的OA活動對象