JS筆記 JS中函式的執行方式

2021-09-10 05:45:44 字數 2910 閱讀 5001

僅做筆記分享,如有錯誤請高手指出

函式無非兩部分:資料和對資料的操作.

資料又分為外部資料和內部資料

內部資料又分為引數和變數兩部分。

在函式每次執行的時候,引數都會被賦予乙個新值,而變數則每次都會被設定為乙個相同的初始值。

函式的變數和引數儲存方式:

對於多個資料來說,最常用儲存方式是使用陣列儲存,這樣按序號查詢起來就比較方便,乙個函式的引數和變數都會集中儲存在乙個資料或者陣列或者跟陣列類似的結構(例如棧)中。但是陣列本身存在乙個缺點,它要求每個元素的長度都相等,這對引數(或變數)來說很難符合要求。但是為了使用陣列(或棧)的便攜性通常會在陣列中儲存乙個包含位址的資料(除位址外,還可能包含資料型別等其他資料),而不是實際的資料,這樣即可以使用陣列,又可以儲存不同長度的資料。此時,在函式中使用引數(或變數)的時候只需要使用「第幾個引數(或變數)」就可以,至於陣列中具體乙個元素使用多少位,需要根據不同的硬體平台(如,32位還是64位)和具體引擎的開發者來確定。但是,這裡還存在乙個小問題,對於複雜的資料來說,這樣儲存無可厚非,而對於直接使用陣列元素就可以儲存的簡單資料(例如整數)來說,在使用這種方式就顯得複雜了,而且多一步通過位址查詢資料的操作也會影響效率,因此這種情況一般會直接將值儲存到陣列中,而不是儲存位址。

函式在每次執行前都會新建乙個引數陣列和乙個變數陣列(也可合併為乙個陣列,而且通常會使用棧來實現),然後將呼叫時所傳遞的引數設定到引數陣列中,而變數陣列在每次執行前都具有相同的內容,對資料進行操作時只需要使用「第幾個引數」或者「第幾個變數」即可。

簡單的資料(如整數)會直接儲存在陣列中,而對於複雜的資料,陣列中只儲存位址,具體的資料儲存在堆中。可以簡單地將堆理解為一堆草紙,其所儲存的資料是所有函式所共享的,不過也並不是每個函式都可以呼叫堆中所有的資料。因為呼叫堆中資料的前提是能找到,若找不到也就不可呼叫。例如,在函式中定義了乙個字串的物件變數s,這時就會將s的內容儲存到堆中,然後將堆中所儲存到堆中,然後將堆中所儲存資料的位址儲存到函式的變數陣列中,這時對於函式外部來說,雖然可以訪問堆中的資料,但是因為沒有s的位址,所以也就無法訪問s這個字串變數了。

function

paramf

(p1)

}paramf

("a"

,"b"

,"c");

//a a b c

函式在執行時會將引數p1和函式中所用到的變數msg、i放到相同的地位,即在函式內部執行的時候就不回區分是引數還是變數。另外,在js的函式中,會自動建立乙個名為arguments的內部變數,然後將所有引數的位址儲存到其中。arguments類似陣列物件,可以通過它來獲取函式呼叫時所傳遞的引數。

function

paramf

(p1)

}paramf

("a"

)//a a

paramf

("a"

,"b"

,"c"

)//a a b c

paramf方法首先列印了引數p1的值,然後便利列印arguments中所有引數的值。可以看出,引數p1的值和arguments[0]的值是一樣的,函式的引數按順序一次儲存在arguments變數中。還可看到,在呼叫函式傳入引數的個數也可以定義時不一樣。例如,雖然paramf函式定義時是有乙個引數,但是在呼叫時卻可以傳遞三個引數,當然也可以傳遞任意個數的引數(不傳也行),因此js中不存在同名函式過載的用法。

函式定義時的引數(通常叫形參)和arguments物件的關係如下:在js的函式呼叫前js引擎會建立乙個arguments物件,然後在其中儲存呼叫時的引數(通常叫實參),而形參其實只是乙個名字,在實際操作時會將其翻譯為arguments物件的乙個元素。例如,對於「console.log(p1)」這條語句,在操作時會被翻譯為「控制台列印arguments的第乙個元素」,即函式的形參只是乙個名字,給程式設計師看的,引擎在實際操作時會自動將其翻譯為arguments中的乙個元素,可以使用下面的例子來驗證。

function

paramf

(p1)

paramf

("hello"

)

在js中可以使用匿名函式,原理很簡單。在js中函式其實也是一種物件,在底層只要用一塊記憶體將其儲存下來即可。在呼叫時只需要找到這塊記憶體,然後建立好執行環境(包含引數陣列、變數陣列等內容)就可以執行了。所以有兩個關鍵方面:

將函式物件儲存到一塊記憶體中

找到這塊記憶體

通常使用通常使用函式名來查詢這塊記憶體的位址,不過函式名只是查詢這塊記憶體的乙個工具,最主要的目的其實是找到這塊記憶體,也就是說,即使沒有函式名也可以,只要能找到這塊記憶體就可以。因此js中可以使用匿名函式。

用法:先使用function關鍵字定義乙個函式,然後將其使用小括號括起來(這只是語法要求,否則後面執行的語句無法被引擎正確識別),這樣九江函式定義好了,引擎會為其分配一塊記憶體來儲存。然後直接在後面加個小括號,並將引數放入其中,這樣引擎就知道要使用這塊記憶體所儲存的函式來執行了。因為對js來說,在函式後面加小括號是呼叫函式的意思,這是js的語法規則。這時既有儲存函式的記憶體也有記憶體位址,這樣就可以執行了。

例子:

var log=

(function()

})()

log(

"hello"

)

這裡也建立了乙個自執行的匿名函式,不過其返回值仍然是乙個匿名函式,也就是說函式自執行後返回的結果仍然是乙個函式。把返回的函式賦值給log變數,就可以使用log變數來呼叫返回的函式了(注意與前面所介紹的函式表示式建立函式的區別)。這裡其實包含兩塊儲存函式的記憶體,自執行的匿名函式本身有一塊記憶體來儲存,當碰到後面表示執行的小括號後就會自動執行,另外還有一塊記憶體來儲存所返回的函式,而返回的值其實是這塊記憶體的位址,這樣log變數指向了這塊儲存函式的記憶體,因此也可以使用log來呼叫此函式。

雖然js表面看起來有很多複雜的東西,但只要理解了其本質(特別是記憶體模型)後就很簡單了。

JS呼叫JS函式的方式

前端基礎知識分享 宣告乙個函式,並呼叫 function func func 使用函式的lambda表示式定義函式,然後呼叫 var func function var宣告了乙個表示式,所以最後有分號 func 將函式賦值給物件的成員後,那麼這個就不在稱為函式,而應該叫做方法 定義乙個函式 var ...

js立即執行函式 JS 函式的執行時機

首先我們介紹一下window.settimeout這個方法,該方法設定乙個定時器,該定時器在定時器到期後執行乙個函式或指定的一段 其語法如下 settimeoutfunction是在到期時間 delay毫秒 之後執行的函式。delay是延遲的毫秒數 一秒等於1000毫秒 函式的呼叫會在該延遲之後發生...

js立即執行函式 《JS 函式的執行時機》

一 當執行下面 時,輸出的是6個6 let 原因 settimeout函式會等當前 執行完後,再執行。從該 中,settimeout會等for迴圈結束後執行,因為for迴圈結束後,i為6,且settimeout被呼叫6次,所以最終輸出6個6 二 將上面 輸出為0 1 2 3 4 5 js用let就能...