JS同名時var 和 function執行順序的問題?
例1:
var a ;
alert( a );
function a(){};
//輸出function a(){};
例2:
function a(){};
var a;
alert(a);
//輸出function a(){};
首先不應該是頁面載入完後function先執行,然後在var 重新定義a嗎 為什麼不管function a(){}怎麼放 a的值永遠都是function a(){};難道我對var的認知出問題了么。。。
是的,當你問出這樣的問題,說明你不了解JavaScript中var聲明和函數聲明的機制。
為了能夠用比較簡單的話語回答這個問題,我就不牽扯太多規範中的專業名字定義了。我假設你應該至少知道執行上下文的概念
JavaScript執行代碼,我這裡簡單分為兩個過程,執行前和執行過程。你問的這個問題答案就出現在執行前階段。JavaScript是這樣的,在執行前時期,會把當前執行上下文的代碼全部掃描一遍,在這個時期生成一個變數對象VO,當所在執行上下文是函數內部時,這個VO會變成激活對象AO。這個VO/AO包括什麼內容呢?
VO/AO包括:變數聲明,函數聲明,以及函數形參。
先不講你那個例子,看下面這段代碼:
```
function
test(a, b) {
var
c = 10;
function
d() {}
var
e = function
_e() {};
(function
x() {});
}
test(10); // call
```
對於上面這段代碼,進入當前執行上下文生成的變數對象內容是(抽象表示):
AO(test) = {
a: 10,
b: undefined,
c: undefined,
d: &
e: undefined
};
所以你看到,在執行前階段,會把我上面說的那三種形式的內容添加到VO/AO中,這一切都發生在執行前。所以,這裡提一句,那所謂的變數聲明提升的原理也是因為這個。
當進入執行階段,每執行一句話,就會去更新這個VO/AO對象。而訪問某個標識符的時候,也是去VO/AO裡面去查找值的。所以,所謂的作用域鏈就是VO/AO的鏈
比如遇到這句話
var c = 10,更新VO/AO對象
VO["c"] = 10;
再回到你的這個例子,對於你這個例子生成的VO/AO如下:
VO ={
x:&
}
為什麼只有函數聲明x呢,這是因為根據規範定義,當執行上下文中具有同名的變數聲明和函數聲明的時候,變數聲明的優先順序是低於函數聲明的,所以函數聲明覆蓋變數聲明。所以,你訪問x時,實際上是存當前執行上文中的VO/AO對象裡面取得,這時候VO/AO對象中x的值就是函數x。
可以了解一下變數提升和函數提升
以function開頭的函數會觸發函數提升,以var聲明的變數會觸發變數提升。
所以
function a () {}
等同於
var aa = function () {}所以代碼中的var a無論放在function a的前還是後,最後在運行時都會先被賦值為function a的方法對象。然後再執行alert(a)
So...JS不於其他解釋型語言,有編譯的階段,類似其他語言的JIT,存在變數和函數提升具體細節可以參考《你不知道的JS(上)》
推薦閱讀:
※原生js 有沒有 手機移動端 滑動 的事件?
※原生 JS 代碼和用 jQuery 實現效果各有什麼優劣勢?
TAG:JavaScript | 前端工程師 | 原生JavaScript | JS調試 |