天天看點

第112天:javascript中函數預解析和執行階段

關于javascript中的函數: 

  1、預解析:把所有的函數定義提前,所有的變量聲明提前,變量的指派不提前 

  2、執行 :從上到下執行,但有例外(setTimeout,setInterval,ajax中的回調函數,事件中的函數需要觸發執行)

函數的參數可以是一個函數,這個函數可以直接調用

  函數可以作為傳回值 

  函數的嵌套形成閉包 

function有雙重身份: 

  1、對象 

  2、構造函數

一、定義

預解析:在目前作用域下,js運作之前,會把帶有var和function關鍵字的事先聲明,并在記憶體中安排好。然後再從上到下執行js語句。

預解析隻會發生在通過var定義的變量和function上。

1、 var

通過var關鍵字定義的變量進行預解析的時候:都是聲明declare,不管它有沒有指派,都會指派undefined。

alert(a); //undefined

var a = 1;

alert(b); //undefined

var b = function(){

}

alert(c); //undefined

var c;

隻要是通過var定義的,不管是變量,還是函數,都是先指派undefined,如果是變量,也不管變量有沒有指派,在預解析階段,都是會被指派為undefined。

2、 function

function進行預解析的時候,不僅是聲明而且還定義(define)了,但是它存儲的資料的那個空間裡面存儲的是代碼是字元串,沒有任何意義。

alert(a); //彈出的是下面的function

function a(){

  alert("預解析function")

3、注意這種情況

定義一個函數想要立即執行,寫成如下形式是不可行的,在預解釋的時候,它把它分解成兩部分來對待,第一部分是fn函數,而第二部分是(),一個匿名函數,執行時會報錯。如果小括号帶參數,如(2),雖然不會報錯,會列印出來2,但并不能把fn執行,也不能當成參數傳遞給fn函數。

function fn(){

//代碼區

}()

如果你想實作立即執行的函數,可以把要執行的函數放到一對括号裡面,對于JavaScript 來說,括弧()裡面不能包含語句,是以在這一點上,解析器在解析function關鍵字的時候,會将相應的代碼解析成function表達式,而不是function聲明是以,隻要将大括号将代碼(包括函數部分和在後面加上一對大括号)全部括起來就可以了。 如下:

(function fn(){

//代碼區...

}())

還可以寫成:閉包。

(function(){

})();

4、 預解析需要注意的情況  

  預解析是發生在目前作用域下的,剛開始的時候,我們預解析的是全局作用域,在js中我們的global就是我們的window。

  我們運作函數的時候會生成一個新的私有作用域(每次執行都是新的,執行完成就銷毀)這個作用域下我們可以了解為開辟了一個新的記憶體空間。在這個記憶體中我們也要執行預解析。當我們的函數執行完成後,這個記憶體或者作用域就會銷毀

  如果在目前作用域下的一個變量沒有預解析,就會向它的上一級去找,直到找到window,如果window下也沒有定義,就會報錯。是以,在函數内通過var定義的變量是局部變量,沒有能過var 定義的變量是全局變量。

  預解析不會在同一個變量上重複的發生,也就是一個變量如果已經在目前作用域下預解析了,不會再重複解析。

等号右邊的function不會進行預解析。

alert(a);

fn();

var a = function fn(){};

第一次列印undefined,第二次報錯,未定義,因為預解析的時候,=号右邊是不進行預解析的。

預解釋是不受其它if或者其它判斷條件影響的,也就是說,即使條件不成立,我們裡面隻要有var或者function也會被預解釋。

if(1==2){

  var a=12;

後面定義的會覆寫前面定義的

alert(a); //彈出後面的function

var b;

alert(a); //仍然彈出後面的function,因為function是提前預解析的

JavaScript“預解析”是分段進行的,準确說是分<script>塊進行的。

當我們的一個函數傳回一個新的function,我們在外面定義一個變量來接收,這樣這個函數的記憶體就不能在執行完成後自動銷毀,也就是我們所謂的函數記憶體被占用了。

變量的值要看它在哪定義,this,要看它在哪調用的。

繼續閱讀