JavaScript學習系列之執行內容與變數對象篇

來源:互聯網
上載者:User

標籤:建立過程   建立   win   經曆   代碼執行   執行   就會   efi   size   

一個熱愛技術的菜鳥...用點滴的積累鑄就明日的達人

本文

  在上一篇文章中講解了JavaScript記憶體模型,其中有提到執行內容與變數對象的概念。對於JavaScript開發人員來說,理解執行內容與變數對象的基本理論知識,是理解閉包,原型鏈的關鍵所在(閉包與原型鏈會在接下來的文章中介紹)。本篇文章就帶你走進JavaScript的執行內容與變數對象,由於本人才疏學淺,若有什麼表述有誤的地方,歡迎各位看官能夠指點一二,在此不勝感激...

  在閱讀這邊文章之前,預設您已經掌握了JavaScript的基本概念、棧堆等基本資料結構以及電腦基本理論基礎,如有瞭解欠缺,請移步相關部落格後再閱讀本文。

一、執行內容

  JavaScript執行程式的時候,會首先建立一個全域的執行內容,將其放入棧中,成為棧底。而後每次執行一個函數的時候,都會去建立一個當前函數的執行內容,然後將其壓入棧中,當函數結束或者返回的時候,再從棧中彈出當前函數的執行內容。執行內容其實就是函數的執行環境,與Java中的棧幀很像,但是與Java不同的是,由於JavaScript是單線程的,所以JavaScript只有一個棧,對所有的執行內容壓棧與出棧都是相對與同一個棧。

  執行內容的生命週期包含三個部分:建立階段、代碼執行階段,執行完畢階段

  • 建立階段:在這個階段中,執行內容會分別建立變數對象,建立範圍鏈,以及確定this的指向
  • 代碼執行階段:建立完成之後,就會開始執行代碼,這個時候,會完成變數賦值,函數引用,以及執行其他代碼。
  • 執行完畢階段:執行完畢之後,就會開始將執行內容出棧,隨後釋放掉所佔用的記憶體

  下面用圖解的方式來描述一下執行內容的壓棧與出棧的步驟,首先先看一段程式

function method_a() {    method_b();    method_c();}function method_b() {}function method_c() {    method_d();}function method_d() {}method_a();

  在開始執行程式的時候,會首先建立一個global的全域執行內容,將其壓入棧中

  隨後執行method_a()的時候,會建立一個method_a的執行內容,將其壓入棧中

  而後,開始執行method_a()函數中的代碼,當執行到第一行的時候,發現要執行method_b()這個函數,所以又開始建立一個method_b的執行內容,將其壓入棧中

  順利的執行完method_b()函數代碼之後,將method_b的執行環境出棧,隨後繼續執行method_a()函數剩下的代碼,發現要執行method_c()函數,所以繼續建立method_c的執行內容,將其壓入棧中

  在執行method_c()函數的時候,發現又要執行method_d()函數,所以又要建立method_d的執行內容,隨後執行完method_d()之後,將其出棧,再之後method_c出棧,method_a出棧,最後剩餘global執行內容

   至此,JavaScript中的執行內容概念介紹完畢...

 

二、變數對象(VO)

  在介紹執行內容的建立階段的時候,有提到變數對象這個概念...本節先來重點瞭解一下變數對象。變數對象的建立,依次經曆了以下幾個過程。

  • 建立arguments對象(參數對象,當某個函數接收參數的時候,會將參數封裝成arguments對象)
  • 檢查當前內容相關的函式宣告,也就是使用function聲明的函數。在變數對象中以函數名建立一個屬性,屬性值為指向該函數所在的記憶體位址的引用。如果函數名的屬性已存在,那麼該屬性將會被新的引用所覆蓋。
  • 檢查當前內容相關的變數聲明,對於每一個變數聲明,變數對象會以變數名建立一個屬性,屬性值為undefined。如果變數名屬性已存在,則會直接跳過,原屬性值保持不變(這樣是為了防止將同名的函數名覆蓋)

  在上面的規則中可以看出,function聲明會比var聲明優先順序更高一點,接下來看一個demo,藉此來學習與驗證一下上述命題

function method(num1, num2) {    console.log(arguments);    console.log(num1, num2);    console.log(vara, func);    console.log(func());    var vara = 10;    console.log(vara);    function func() {        return 1;    }    function func() {        return 2;    }}method(1, 2);

  輸出結果如下

{ ‘0‘: 1, ‘1‘: 2 }1 2undefined [Function: func]210

  首先輸出的是arguments對象,通過與第二行輸出num1,num2對比可知,argument對象是一種key-value格式的對象,其中key從0開始逐步遞增,value依次對應著傳入參數。

  隨後根據變數聲明與函式宣告的規則,由於變數聲明,會在執行內容建立階段為變數賦值undefined,而函式宣告,會在執行內容建立階段為函數變數賦值指向該函數的引用地址。故第三行輸出結果為 undefined 與 [Function:func]

  又由於代碼中聲明了兩個func函數,為了驗證是否存在函數覆蓋現象,列印輸出func()的結果,輸出結果為2,則意味著,第二個定義的func函數,在執行內容階段,覆蓋了一開始的func函數。

  最後給vara賦值10,隨即輸出vara,得到10

 三、OV與AO

  在初學JavaScipt中,總會有同學對變數對象與使用中的物件弄混,為此解釋一下這兩個名詞。在執行內容建立的階段會建立變數對象,變數對象中儲存arguments,function聲明的函數,var聲明的變數,具體的第二節已經介紹,在此不做過多闡述。當執行內容建立過程的結束,就開始了代碼執行階段,在此時JavaScript會將變數對象(VO)轉換成使用中的物件(AO)。在未進入到執行階段之前,變數對象中的屬性都不能訪問,但是進入執行階段後,由於變數對象被轉換成了使用中的物件,裡面的屬性就可以被訪問了,隨後開始執行代碼。因此在第二節的例子上,其實輸出的都是使用中的物件的屬性(但變數對象與使用中的物件中包含的屬性與值都相同,所以姑且認為是變數對象)

  再總結一下,其實變數對象與使用中的物件都是同一個對象,只是它們處於不同的執行內容生命週期。

四、全域變數對象

  以瀏覽器為例,全域變數對象為window對象。除此之外,全域變數對象的生命週期與執行內容一致,所以如果瀏覽器視窗如果不關閉的話,全域變數對象將會一直存在。

JavaScript學習系列之執行內容與變數對象篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.