日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

js代码执行过程

發(fā)布時間:2024/5/24 综合教程 61 生活家
生活随笔 收集整理的這篇文章主要介紹了 js代码执行过程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  當(dāng)瀏覽器加載了js代碼之后,發(fā)生什么?js引擎怎么工作?編譯器做了什么?

  以及執(zhí)行環(huán)境對象、作用域鏈、活動對象、變量對象 是什么?

  以及作用域鏈?zhǔn)裁磿r候創(chuàng)建、銷毀?等等,這些對象的生命周期都會在js代碼執(zhí)行過程得到一一的體現(xiàn)

 先粗淺地了解下流程:

<script src='app.js'></script>
<script>
    var name = "Tom";

    function getInfo(){
        return name;
    }

    getInfo();
</script>
<script>
    var sex = 'male';
</script>

  1. 瀏覽器載入第一個代碼段后,開始進行語法檢測(書寫是否正確等);之后,如果還有代碼段,繼續(xù)載入,語法檢查;直到?jīng)]有了代碼段;

  2. js引擎 創(chuàng)建全局執(zhí)行環(huán)境,同時生成作用域鏈、變量對象;將全局執(zhí)行對象棧入環(huán)境棧中;(在瀏覽器中全局執(zhí)行對象為window;全局執(zhí)行環(huán)境在退出程序時銷毀;)

  3. 編譯器開始對全局執(zhí)行環(huán)境中的var/function聲明進行預(yù)解析;如果全局執(zhí)行環(huán)境的變量對象中沒有name、getInfo等,就添加它們

  4. 編譯器預(yù)解析后,生成代碼;js引擎開始執(zhí)行代碼;

以上幾個步驟是非常粗淺的,省卻了很多細節(jié),但是js代碼從加載到瀏覽器到執(zhí)行完,基本就是這個過程;

下面結(jié)合代碼、圖表、解釋等重新、詳細地講解下js代碼的執(zhí)行過程,這里舉兩個例子,一個是基本簡單的流程,一個則涉及到閉包;

一個基本簡單的例子:

var name = "Tom";

function getInfo(){

    var nation = "China";

    return name + nation;

}

getInfo();

  1. 編譯器進行語法檢測

  2. js引擎創(chuàng)建全局執(zhí)行環(huán)境對象window,此時生成作用域鏈scope1,變量對象

  

  3. 編譯器 對 var/function 聲明的變量、函數(shù)預(yù)處理;將聲明的變量name添加到變量對象中,值為undefined;

   function聲明的函數(shù)變量添加到變量對象中,同時將作用域鏈scope1保存在[[scope]]屬性中;

   同時,將全局執(zhí)行環(huán)境棧入環(huán)境棧中;

  

    注1:函數(shù)的作用域鏈在函數(shù)聲明時就已經(jīng)創(chuàng)建,保存在內(nèi)部屬性[[scope]]中;在函數(shù)調(diào)用的時候會再次創(chuàng)建作用域鏈,用于延伸;

    注2:此時編譯器沒有對getInfo函數(shù)體做任何操作,

    注3:對var/function聲明的變量預(yù)處理時,涉及到聲明提前,函數(shù)聲明優(yōu)先的規(guī)則

    這一步處理完之后的代碼相當(dāng)于:

 1 function getInfo(){
 2     // 編譯器此時沒有對函數(shù)體中操作;
 3     // 只有函數(shù)被調(diào)用時,編譯器才會處理函數(shù)體
 4     var nation = "China";
 5 
 6     return name + nation;
 7 
 8 }
 9 
10 var name;
11 
12 name = "Tom";
13 
14 getInfo();    

  4. 編譯器生成代碼,js引擎開始執(zhí)行代碼

    4.1 代碼執(zhí)行到12行時,js引擎 找到環(huán)境棧中頂部執(zhí)行對象, 然后根據(jù)作用域鏈查找變量對象,發(fā)現(xiàn)變量對象中存在name,則賦值name="Tom"

    4.2 代碼執(zhí)行到14行時,js引擎調(diào)用getInfo函數(shù)

      4.2.1 創(chuàng)建getInfo執(zhí)行環(huán)境,同時生成作用域鏈,活動對象;

         此時生成的作用域鏈會將函數(shù)[[scope]]保存的scope1復(fù)制過來,再添加上新生成的getInfo活動對象;

         活動對象在生成時,會生成arguments對象;

         注:變量對象、活動對象區(qū)別

變量對象:在生成全局執(zhí)行環(huán)境時生成,不包含arguments

          活動對象:在調(diào)用函數(shù),生成函數(shù)執(zhí)行環(huán)境時生成,包含arguments對象

講述到現(xiàn)在一直沒有出現(xiàn)作用域的概念,本人認為變量對象、活動對象就可以看成作用域;

      4.2.2 將getInfo執(zhí)行環(huán)境對象棧入環(huán)境棧中,編譯器開始對 var/function聲明的變量預(yù)解析

        

        預(yù)解析后,相當(dāng)于下面的代碼:

 1 function getInfo(){
 2    
 3     var nation;
 4 
 5     nation = "China";
 6 
 7     return name + nation;
 8 
 9 }
10 
11 var name;
12 
13 name = "Tom";
14 
15 getInfo();

      4.2.3 編譯器生成代碼,js引擎開始執(zhí)行

        4.2.3.1 執(zhí)行到第5行,通過作用域鏈找到nation,然后賦值;

4.2.3.2 執(zhí)行到第7行, 通過作用域鏈找到name,然后返回值

4.2.3.3 函數(shù)執(zhí)行完,銷毀getInfo活動對象、作用域鏈,將getInfo執(zhí)行環(huán)境棧出,銷毀;控制權(quán)交給環(huán)境棧中最頂部的執(zhí)行環(huán)境;

基本簡單的流程就是這樣,如果有閉包,即使沒有調(diào)用閉包,閉包[[scope]]指向的作用域鏈涉及的變量對象、活動對象不會銷毀;

一個閉包相關(guān)的流程:

var name = "Tom";

function getInfo(){

    var nation = "China";

    function sumIn(){
        return name + nation;
    }

    return sumIn();
}

getInfo();

一個相對復(fù)雜的流程:

var name="Hello World";
var obj = {
    name:'obj Object',

    getName:function(){

        console.log( name );

        console.log(this.name);

    }
}
obj.getName();

明晰這個流程,必須對作用域鏈非常了解;作用域鏈只與函數(shù)相關(guān),跟對象無關(guān);

  

    

總結(jié)

以上是生活随笔為你收集整理的js代码执行过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。