做爰高潮a片〈毛片〉,尤物av天堂一区二区在线观看,一本久久A久久精品VR综合,添女人荫蒂全部过程av

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

對于Javascript 執行上下文的全面了解

來源:懂視網 責編:小采 時間:2020-11-27 22:30:57
文檔

對于Javascript 執行上下文的全面了解

對于Javascript 執行上下文的全面了解:在這篇文章中,將比較深入地闡述下執行上下文 – JavaScript中最基礎也是最重要的一個概念。相信讀完這篇文章后,你就會明白javascript引擎內部在執行代碼以前到底做了些什么,為什么某些函數以及變量在沒有被聲明以前就可以被使用,以及它們的最終的值是怎樣
推薦度:
導讀對于Javascript 執行上下文的全面了解:在這篇文章中,將比較深入地闡述下執行上下文 – JavaScript中最基礎也是最重要的一個概念。相信讀完這篇文章后,你就會明白javascript引擎內部在執行代碼以前到底做了些什么,為什么某些函數以及變量在沒有被聲明以前就可以被使用,以及它們的最終的值是怎樣

在這篇文章中,將比較深入地闡述下執行上下文 – JavaScript中最基礎也是最重要的一個概念。相信讀完這篇文章后,你就會明白javascript引擎內部在執行代碼以前到底做了些什么,為什么某些函數以及變量在沒有被聲明以前就可以被使用,以及它們的最終的值是怎樣被定義的。

什么是執行上下文

Javascript中代碼的運行環境分為以下三種:

全局級別的代碼 – 這個是默認的代碼運行環境,一旦代碼被載入,引擎最先進入的就是這個環境。

函數級別的代碼 – 當執行一個函數時,運行函數體中的代碼。

Eval的代碼 – 在Eval函數內運行的代碼。

在網上可以找到很多闡述作用域的資源,為了使該文便于大家理解,我們可以將“執行上下文”看做當前代碼的運行環境或者作用域。下面我們來看一個示例,其中包括了全局以及函數級別的執行上下文:

上圖中,一共用4個執行上下文。紫色的代表全局的上下文;綠色代表person函數內的上下文;藍色以及橙色代表person函數內的另外兩個函數的上下文。注意,不管什么情況下,只存在一個全局的上下文,該上下文能被任何其它的上下文所訪問到。也就是說,我們可以在person的上下文中訪問到全局上下文中的sayHello變量,當然在函數firstName或者lastName中同樣可以訪問到該變量。

至于函數上下文的個數是沒有任何限制的,每到調用執行一個函數時,引擎就會自動新建出一個函數上下文,換句話說,就是新建一個局部作用域,可以在該局部作用域中聲明私有變量等,在外部的上下文中是無法直接訪問到該局部作用域內的元素的。在上述例子的,內部的函數可以訪問到外部上下文中的聲明的變量,反之則行不通。那么,這到底是什么原因呢?引擎內部是如何處理的呢?

執行上下文堆棧

在瀏覽器中,javascript引擎的工作方式是單線程的。也就是說,某一時刻只有唯一的一個事件是被激活處理的,其它的事件被放入隊列中,等待被處理。下面的示例圖描述了這樣的一個堆棧:

我們已經知道,當javascript代碼文件被瀏覽器載入后,默認最先進入的是一個全局的執行上下文。當在全局上下文中調用執行一個函數時,程序流就進入該被調用函數內,此時引擎就會為該函數創建一個新的執行上下文,并且將其壓入到執行上下文堆棧的頂部。瀏覽器總是執行當前在堆棧頂部的上下文,一旦執行完畢,該上下文就會從堆棧頂部被彈出,然后,進入其下的上下文執行代碼。這樣,堆棧中的上下文就會被依次執行并且彈出堆棧,直到回到全局的上下文。請看下面一個例子:

(function foo(i) {
 if (i === 3) {
 return;
 }
 else {
 foo(++i);
 }
 }(0));

上述foo被聲明后,通過()運算符強制直接運行了。函數代碼就是調用了其自身3次,每次是局部變量i增加1。每次foo函數被自身調用時,就會有一個新的執行上下文被創建。每當一個上下文執行完畢,該上上下文就被彈出堆棧,回到上一個上下文,直到再次回到全局上下文。真個過程抽象如下圖:

由此可見 ,對于執行上下文這個抽象的概念,可以歸納為以下幾點:

單線程

同步執行

唯一的一個全局上下文

函數的執行上下文的個數沒有限制

每次某個函數被調用,就會有個新的執行上下文為其創建,即使是調用的自身函數,也是如此。

執行上下文的建立過程

我們現在已經知道,每當調用一個函數時,一個新的執行上下文就會被創建出來。然而,在javascript引擎內部,這個上下文的創建過程具體分為兩個階段:

建立階段(發生在當調用一個函數時,但是在執行函數體內的具體代碼以前)

建立變量,函數,arguments對象,參數

建立作用域鏈

確定this的值

代碼執行階段:

變量賦值,函數引用,執行其它代碼

實際上,可以把執行上下文看做一個對象,其下包含了以上3個屬性:

 (executionContextObj = {
 variableObject: { /* 函數中的arguments對象, 參數, 內部的變量以及函數聲明 */ },
 scopeChain: { /* variableObject 以及所有父執行上下文中的variableObject */ },
 this: {}
 }

建立階段以及代碼執行階段的詳細分析

確切地說,執行上下文對象(上述的executionContextObj)是在函數被調用時,但是在函數體被真正執行以前所創建的。函數被調用時,就是我上述所描述的兩個階段中的第一個階段 – 建立階段。這個時刻,引擎會檢查函數中的參數,聲明的變量以及內部函數,然后基于這些信息建立執行上下文對象(executionContextObj)。在這個階段,variableObject對象,作用域鏈,以及this所指向的對象都會被確定。

上述第一個階段的具體過程如下:

找到當前上下文中的調用函數的代碼

在執行被調用的函數體中的代碼以前,開始創建執行上下文

進入第一個階段-建立階段:

建立variableObject對象:

建立arguments對象,檢查當前上下文中的參數,建立該對象下的屬性以及屬性值

檢查當前上下文中的函數聲明:

每找到一個函數聲明,就在variableObject下面用函數名建立一個屬性,屬性值就是指向該函數在內存中的地址的一個引用

如果上述函數名已經存在于variableObject下,那么對應的屬性值會被新的引用所覆蓋。

初始化作用域鏈

確定上下文中this的指向對象

代碼執行階段:

執行函數體中的代碼,一行一行地運行代碼,給variableObject中的變量屬性賦值。

下面來看個具體的代碼示例:

 function foo(i) {
 var a = 'hello';
 var b = function privateB() {
 
 };
 function c() {
 
 }
 }
 
 foo(22);

在調用foo(22)的時候,建立階段如下:


 fooExecutionContext = {
 variableObject: {
 arguments: {
 0: 22,
 length: 1
 },
 i: 22,
 c: pointer to function c()
 a: undefined,
 b: undefined
 },
 scopeChain: { ... },
 this: { ... }
 }

由此可見,在建立階段,除了arguments,函數的聲明,以及參數被賦予了具體的屬性值,其它的變量屬性默認的都是undefined。一旦上述建立階段結束,引擎就會進入代碼執行階段,這個階段完成后,上述執行上下文對象如下:

 fooExecutionContext = {
 variableObject: {
 arguments: {
 0: 22,
 length: 1
 },
 i: 22,
 c: pointer to function c()
 a: 'hello',
 b: pointer to function privateB()
 },
 scopeChain: { ... },
 this: { ... }
 }

我們看到,只有在代碼執行階段,變量屬性才會被賦予具體的值。

局部變量作用域提升的緣由

在網上一直看到這樣的總結: 在函數中聲明的變量以及函數,其作用域提升到函數頂部,換句話說,就是一進入函數體,就可以訪問到其中聲明的變量以及函數。這是對的,但是知道其中的緣由嗎?相信你通過上述的解釋應該也有所明白了。不過在這邊再分析一下。

看下面一段代碼:

 (function() {
 console.log(typeof foo); // function pointer
 console.log(typeof bar); // undefined
 
 var foo = 'hello',
 bar = function() {
 return 'world';
 };
 
 function foo() {
 return 'hello';
 }
 
 }());​

上述代碼定義了一個匿名函數,并且通過()運算符強制理解執行。那么我們知道這個時候就會有個執行上下文被創建,我們看到例子中馬上可以訪問foo以及bar變量,并且通過typeof輸出foo為一個函數引用,bar為undefined。

為什么我們可以在聲明foo變量以前就可以訪問到foo呢?

因為在上下文的建立階段,先是處理arguments, 參數,接著是函數的聲明,最后是變量的聲明。那么,發現foo函數的聲明后,就會在variableObject下面建立一個foo屬性,其值是一個指向函數的引用。當處理變量聲明的時候,發現有var foo的聲明,但是variableObject已經具有了foo屬性,所以直接跳過。當進入代碼執行階段的時候,就可以通過訪問到foo屬性了,因為它已經就存在,并且是一個函數引用。

為什么bar是undefined呢?

因為bar是變量的聲明,在建立階段的時候,被賦予的默認的值為undefined。由于它只要在代碼執行階段才會被賦予具體的值,所以,當調用typeof(bar)的時候輸出的值為undefined。

好了,到此為止,相信你應該對執行上下文有所理解了,這個執行上下文的概念非常重要,務必好好搞懂之!

以上這篇對于Javascript 執行上下文的全面了解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

對于Javascript 執行上下文的全面了解

對于Javascript 執行上下文的全面了解:在這篇文章中,將比較深入地闡述下執行上下文 – JavaScript中最基礎也是最重要的一個概念。相信讀完這篇文章后,你就會明白javascript引擎內部在執行代碼以前到底做了些什么,為什么某些函數以及變量在沒有被聲明以前就可以被使用,以及它們的最終的值是怎樣
推薦度:
標簽: js 了解 javascript
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 桐梓县| 平安县| 清丰县| 广东省| 崇仁县| 上高县| 永修县| 湘潭县| 高台县| 绥滨县| 邻水| 宣化县| 资兴市| 岳普湖县| 金溪县| 富平县| 宕昌县| 宁夏| 屏山县| 榆林市| 前郭尔| 安国市| 盘山县| 交城县| 青冈县| 伊春市| 都兰县| 桐梓县| 星子县| 阿拉善左旗| 夏邑县| 昆山市| 博湖县| 长寿区| 嘉黎县| 阳曲县| 安宁市| 洞口县| 珠海市| 综艺| 沐川县|