js預編譯過程

先科普:java

1.javaScript是解釋型語言,就是編譯一行,執行一行.....
2.javaScript沒有塊級及做用域......
3.javaScript具備變量和函數聲明提高功能.....
4.AO對象和GO對象....
5.預編譯就是解決代碼執行順序問題,與java語言相似(jvm)....數組

例如:app

(function(a){
console.log(a);
var a = 12;
console.log(a);
function a(){...}
console.log(a);
var b = function(){...}
console.log(b);
function d(){...}
})(1);

1.首先建立一個GO對象,和AO對象....[由於該當即執行函數是在全局做用域中執行的,當即執行函數執行時建立AO對象]jvm

GO{
   AO{
       
   } 
}

2.找形參和變量聲明,將變量和形參名做爲AO屬性名,值爲undefined....【變量聲明找到了a和b,其實形參也是一種變量聲明,相似於function(a,b){var a,b;},這裏的形參和函數裏的變量聲明a重名了,那麼後一個變量聲明會被忽略...】函數

GO{
    AO{
       a: undefined,
       b: undefined 
    }
}

3.將實參和形參統一......【實參值賦值給形參】this

GO{
    AO{
        a: 1,
        b: undefined
    }
}

4.在函數體裏面找函數聲明,值賦予函數體....【記住,必定是變量聲明在前,函數聲明在後。因此變量聲明提高和函數聲明提高會出現一個前後順序】code

GO{
    AO{
        a: function(){...},
        b: undefined,
        d: function(){...}
    }
}

預編譯過程結束。對象

而後開始執行:ip

1.執行第一行:輸出function(){...}
2.執行第二行賦值:作用域

GO{
    AO{
        a: 12,
        b: undefined,
        d: function(){...}
    }
}

3.執行第三行:輸出12
4.第四行是函數聲明,預編譯已經執行了,跳過,執行第五行,輸出:12
5.執行第六行賦值:

GO{
    AO{
        a: 12,
        b: function(){...},
        d: function(){...}
    }
}

6.執行第七行:輸出:function(){...}
7.第八行是函數聲明,跳過,執行完成...接下來銷燬AO,再銷燬GO【這裏是一個js垃圾清理過程,無關本話題】

例如:
做用域鏈......
本身自己屬性找不到就會去查找上一級的做用域中的屬性...層層迭代查詢
直到查到爲止....
js是根據一個叫[[scope]]的屬性查找的,[[scope]]是任何函數(做用域都存在)都默認自帶的屬性,它保存了一個數組值,長度是父級的總長度(做用域包裹的層級,長度至少爲1),直到window爲止,若是查不到,彈出錯誤...
首先[[scope]][0]保存自身預編譯AO,先查找[[scope]][0],保存了該AO或者GO....
不存在時查找[[scope]][1]...
...
注意:[[scope]]屬性不可枚舉,沒法訪問...

例如:
call和apply擴展了做用域....
apply方法能夠‘借用’其餘對象中的方法(簡稱A)完成屬於本身的任務,A只是暫時用於自身,其自己仍是別人的,你不能夠去修改A中的代碼,也沒法修改...在你調用A時,apply中this指向了自身,能夠這樣理解:我使用了你的方法,方法裏的this指向了我,個人屬性(方法)增長了一項(擴展了個人做用域),可是一旦退出apply時(執行完成後),方法依然要還給你,this指向仍是你,個人做用域迴歸原樣....

相關文章
相關標籤/搜索