亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript從定義到執行 你不知道的那些事

2019-11-20 10:51:58
字體:
來源:轉載
供稿:網友

javascript從定義到執行,JS引擎在實現層做了很多初始化工作,因此在學習JS引擎工作機制之前,我們需要引入幾個相關的概念:執行環境棧、全局對象、執行環境、變量對象、活動對象、作用域和作用域鏈等,這些概念正是JS引擎工作的核心組件。

這篇文章的目的不是孤立的為你講解每一個概念,而是通過一個簡單的demo來展開分析,全局講解JS引擎從定義到執行的每一個細節,以及這些概念在其中所扮演的角色。

var x = 1; //定義一個全局變量 xfunction A(y){  var x = 2; //定義一個局部變量 x  function B(z){ //定義一個內部函數 B    console.log(x+y+z);  }  return B; //返回函數B的引用}var C = A(1); //執行A,返回BC(1); //執行函數B

這個demo是一個閉包,執行結果是4,下面我們將分全局初始化、執行函數A、執行函數B 三個階段來分析JS引擎的工作機制:

一、全局初始化

JS引擎在進入一段可執行的代碼時,需要完成以下三個初始化工作:

首先,創建一個全局對象(Global Object) , 這個對象全局只存在一份,它的屬性在任何地方都可以訪問,它的存在伴隨著應用程序的整個生命周期。全局對象在創建時,將Math,String,Date,document 等常用的JS對象作為其屬性。由于這個全局對象不能通過名字直接訪問,因此還有另外一個屬性window,并將window指向了自身,這樣就可以通過window訪問這個全局對象了。用偽代碼模擬全局對象的大體結構如下:

//創建一個全局對象var globalObject = {   Math:{},  String:{},  Date:{},  document:{}, //DOM操作  ...  window:this //讓window屬性指向了自身}

然后,JS引擎需要構建一個執行環境棧( Execution Context Stack) ,與此同時,也要創建一個全局執行環境(Execution Context)EC ,并將這個全局執行環境EC壓入執行環境棧中。執行環境棧的作用是為了保證程序能夠按照正確的順序被執行。在javascript中,每個函數都有自己的執行環境,當執行一個函數時,該函數的執行環境就會被推入執行環境棧的頂部并獲取執行權。當這個函數執行完畢,它的執行環境又從這個棧的頂部被刪除,并把執行權并還給之前執行環境。我們用偽代碼來模擬執行環境棧和EC的關系:

var ECStack = []; //定義一個執行環境棧,類似于數組var EC = {};  //創建一個執行空間,//ECMA-262規范并沒有對EC的數據結構做明確的定義,你可以理解為在內存中分配的一塊空間ECStack.push(EC); //進入函數,壓入執行環境ECStack.pop(EC); //函數返回后,刪除執行環境

最后,JS引擎還要創建一個與EC關聯的全局變量對象(Varibale Object) VO,  并把VO指向全局對象,VO中不僅包含了全局對象的原有屬性,還包括在全局定義的變量x 和函數 A,與此同時,在定義函數A的時候,還為 A 添加了一個內部屬性scope,并將scope指向了VO。每個函數在定義的時候,都會創建一個與之關聯的scope屬性,scope總是指向定義函數時所在的環境。此時的ECStack結構如下:

ECStack = [  //執行環境棧  EC(G) = {  //全局執行環境    VO(G):{ //定義全局變量對象      ... //包含全局對象原有的屬性      x = 1; //定義變量x      A = function(){...}; //定義函數A      A[[scope]] = this; //定義A的scope,并賦值為VO本身    }  }];

二、 執行函數A

當執行進入A(1) 時,JS引擎需要完成以下工作:

首先,JS引擎會創建函數A的執行環境EC,然后EC推入執行環境棧的頂部并獲取執行權。此時執行環境棧中有兩個執行環境,分別是全局執行環境和函數A執行環境,A的執行環境在棧頂,全局執行環境在棧的底部。然后,創建函數A的作用域鏈(Scope Chain) ,在javascript中,每個執行環境都有自己的作用域鏈,用于標識符解析,當執行環境被創建時,它的作用域鏈就初始化為當前運行函數的scope所包含的對象。 

接著,JS引擎會創建一個當前函數的活動對象(Activation Object) AO,這里的活動對象扮演著變量對象的角色,只是在函數中的叫法不同而已(你可以認為變量對象是一個總的概念,而活動對象是它的一個分支), AO中包含了函數的形參、arguments對象、this對象、以及局部變量和內部函數的定義,然后AO會被推入作用域鏈的頂端。需要注意的是,在定義函數B的時候,JS引擎同樣也會為B添加了一個scope屬性,并將scope指向了定義函數B時所在的環境,定義函數B的環境就是A的活動對象AO, 而AO位于鏈表的前端,由于鏈表具有首尾相連的特點,因此函數B的scope指向了A的整個作用域鏈。 我們再看看此時的ECStack結構:

ECStack = [  //執行環境棧  EC(A) = {  //A的執行環境    [scope]:VO(G), //VO是全局變量對象    AO(A) : { //創建函數A的活動對象      y:1,      x:2, //定義局部變量x      B:function(){...}, //定義函數B      B[[scope]] = this; //this指代AO本身,而AO位于scopeChain的頂端,因此B[[scope]]指向整個作用域鏈      arguments:[],//平時我們在函數中訪問的arguments就是AO中的arguments      this:window //函數中的this指向調用者window對象    },    scopeChain:<AO(A),A[[scope]]> //鏈表初始化為A[[scope]],然后再把AO加入該作用域鏈的頂端,此時A的作用域鏈:AO(A)->VO(G)  },  EC(G) = {  //全局執行環境    VO(G):{ //創建全局變量對象      ... //包含全局對象原有的屬性      x = 1; //定義變量x      A = function(){...}; //定義函數A      A[[scope]] = this; //定義A的scope,A[[scope]] == VO(G)    }  }];

三、 執行函數B

函數A被執行以后,返回了B的引用,并賦值給了變量C,執行 C(1) 就相當于執行B(1),JS引擎需要完成以下工作:

首先,還和上面一樣,創建函數B的執行環境EC,然后EC推入執行環境棧的頂部并獲取執行權。 此時執行環境棧中有兩個執行環境,分別是全局執行環境和函數B的執行環境,B的執行環境在棧頂,全局執行環境在棧的底部。(注意:當函數A返回后,A的執行環境就會從棧中被刪除,只留下全局執行環境)然后,創建函數B的作用域鏈,并初始化為函數B的scope所包含的對象,即包含了A的作用域鏈。最后,創建函數B的活動對象AO,并將B的形參z, arguments對象 和 this對象作為AO的屬性。此時ECStack將會變成這樣:

ECStack = [  //執行環境棧  EC(B) = {  //創建B的執行環境,并處于作用域鏈的頂端    [scope]:AO(A), //指向函數A的作用域鏈,AO(A)->VO(G)    var AO(B) = { //創建函數B的活動對象      z:1,      arguments:[],      this:window    }    scopeChain:<AO(B),B[[scope]]> //鏈表初始化為B[[scope]],再將AO(B)加入鏈表表頭,此時B的作用域鏈:AO(B)->AO(A)-VO(G)  },  EC(A), //A的執行環境已經從棧頂被刪除,  EC(G) = {  //全局執行環境    VO:{ //定義全局變量對象      ... //包含全局對象原有的屬性      x = 1; //定義變量x      A = function(){...}; //定義函數A      A[[scope]] = this; //定義A的scope,A[[scope]] == VO(G)    }  }];

當函數B執行“x+y+z”時,需要對x、y、z 三個標識符進行一一解析,解析過程遵守變量查找規則:先查找自己的活動對象中是否存在該屬性,如果存在,則停止查找并返回;如果不存在,繼續沿著其作用域鏈從頂端依次查找,直到找到為止,如果整個作用域鏈上都未找到該變量,則返回“undefined”。從上面的分析可以看出函數B的作用域鏈是這樣的:

AO(B)->AO(A)->VO(G)
因此,變量x會在AO(A)中被找到,而不會查找VO(G)中的x,變量y也會在AO(A)中被找到,變量z 在自身的AO(B)中就找到了。所以執行結果:2+1+1=4.

簡單的總結語

了解了JS引擎的工作機制之后,我們不能只停留在理解概念的層面,而要將其作為基礎工具,用以優化和改善我們在實際工作中的代碼,提高執行效率,產生實際價值才是我們的真正目的。就拿變量查找機制來說,如果你的代碼嵌套很深,每引用一次全局變量,JS引擎就要查找整個作用域鏈,比如處于作用域鏈的最底端window和document對象就存在這個問題,因此我們圍繞這個問題可以做很多性能優化的工作,當然還有其他方面的優化,此處不再贅述,本文僅當作拋磚引玉吧!

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97久久久免费福利网址| 欧美激情免费看| 国产亚洲激情在线| 日韩精品高清在线| 日本韩国在线不卡| 亚洲一区二区三区视频| 韩国福利视频一区| 欧美大尺度在线观看| 国产免费成人av| 国产精品入口福利| 久久成年人免费电影| 国产成人啪精品视频免费网| www.日韩.com| 日韩中文视频免费在线观看| 97超级碰碰人国产在线观看| 国产成人精品免费久久久久| 亚洲国产精品人久久电影| 91久久国产精品91久久性色| 亚洲成年人在线| 成人免费在线视频网址| 亚洲区免费影片| 精品国偷自产在线视频| 高清欧美性猛交xxxx| 国产中文字幕91| 97碰碰碰免费色视频| 国产精品福利久久久| 亚洲第一天堂av| 欧美精品videos性欧美| 欧美日韩国产影院| 中日韩美女免费视频网站在线观看| 欧美性videos高清精品| 日韩欧美在线播放| 久久久999精品| 欧美高清在线视频观看不卡| 亚洲一区二区国产| 欧美国产日本在线| 久久精品成人动漫| 欧美在线一级va免费观看| 久久久久成人精品| 欧美成人中文字幕在线| 国产精品日日摸夜夜添夜夜av| 久久久亚洲欧洲日产国码aⅴ| 欧美另类暴力丝袜| 国产精品久久久久99| 国产成人中文字幕| 久久国产加勒比精品无码| 综合欧美国产视频二区| 精品视频9999| 亚洲iv一区二区三区| 欧洲成人午夜免费大片| 欧美日韩中文字幕日韩欧美| 欧美日韩在线免费| 亚洲欧美综合图区| 精品精品国产国产自在线| 欧美超级免费视 在线| 国产精品美女免费视频| 国产精品久久久久久av福利软件| 亚洲新中文字幕| 国产精品福利久久久| 97在线视频一区| 亚洲精品wwwww| 亚洲欧美国内爽妇网| 久久久最新网址| 亚洲小视频在线| 91精品国产91| 久久久精品久久久久| 国产精品91久久| 2019中文字幕全在线观看| 不卡av电影在线观看| 国产日韩欧美中文在线播放| 精品福利樱桃av导航| 精品成人69xx.xyz| 日韩成人中文电影| 国产精品久久久久久久久免费看| 日韩精品免费视频| 最新91在线视频| 久久精品成人欧美大片古装| 九九热这里只有精品6| 久久好看免费视频| 亚洲成人亚洲激情| 国产日韩欧美视频在线| 亚洲精品wwwww| 久久亚洲精品中文字幕冲田杏梨| 欧美中文字幕在线观看| 日韩免费在线视频| 国产精品久久久久不卡| 久久理论片午夜琪琪电影网| 日韩av在线免费看| 欧洲日韩成人av| 日韩美女写真福利在线观看| 日韩av有码在线| 欧美精品激情在线观看| 久久精品99久久久香蕉| 亚洲精品电影网| 日韩经典中文字幕在线观看| 欧美日韩中国免费专区在线看| 日韩精品免费一线在线观看| 91免费国产网站| 久久久这里只有精品视频| 在线观看精品自拍私拍| 亚洲精品中文字幕有码专区| 欧美视频中文字幕在线| 美日韩精品免费观看视频| 国产99久久精品一区二区| 亚洲最大成人在线| 成人黄色生活片| 26uuu日韩精品一区二区| 欧美日韩亚洲成人| 成年无码av片在线| 色哟哟入口国产精品| 精品久久久国产| 亚洲福利在线观看| www欧美xxxx| 亚洲免费人成在线视频观看| 国产亚洲精品va在线观看| 欧美日韩在线另类| 精品一区二区三区电影| 日韩大片免费观看视频播放| 国产精品精品视频一区二区三区| 欧美老肥婆性猛交视频| 欧美精品在线观看| 欧美成人精品不卡视频在线观看| 国产精品美女在线| 影音先锋日韩有码| 成人午夜在线影院| 亚洲国产中文字幕久久网| 日韩免费在线免费观看| 国外成人在线直播| 久久九九热免费视频| 91精品国产91久久久久久不卡| 国产精品免费观看在线| 国产精品久久久久不卡| 欧美丝袜第一区| 国产一区二区三区在线看| 亚洲999一在线观看www| 国产97色在线| 欧美日韩精品在线| 国产999在线| 中文字幕在线日韩| 日韩精品福利网站| 成人黄色免费片| 欧美性猛交丰臀xxxxx网站| 国产精品igao视频| 成人久久久久爱| www.亚洲一二| 日韩欧美亚洲范冰冰与中字| 久久免费少妇高潮久久精品99| 亚洲直播在线一区| 欧美激情图片区| 久久国产一区二区三区| 国产日韩欧美黄色| 国产精品日韩在线一区| 国产综合久久久久| 久久久免费高清电视剧观看| 欧美—级a级欧美特级ar全黄| 国产精品午夜视频| 亚洲欧美日韩中文在线制服| 国产在线视频2019最新视频| 欧美最猛性xxxx| 2019国产精品自在线拍国产不卡| 亚洲老板91色精品久久| 色爱av美腿丝袜综合粉嫩av| 久久久国产视频| 国产日韩欧美一二三区|