EC+VO+SCOPE for ES3

詞法環境

詞法作用域

詞法作用域(lexcical scope)。即JavaScript變量的作用域是在定義時決定而不是執行時決定,也就是說詞法作用域取決于源碼。

詞法環境

用于定義特定變量和函數標識符在ECMAScript代碼的詞法嵌套結構上的關聯關系, 一個詞法環境由一個環境記錄項和可能為空的外部詞法環境引用構成

詞法環境 = 詞法環境記錄項 + 外部詞法環境
外部詞法環境是包含內部詞法環境的詞法環境, 外部詞法環境可能有多個內部詞法環境

環境記錄項 = 聲明式環境記錄項 || 對象式環境記錄項

執行環境

  • javascript引擎在執行每個函數實例時,都會創建一個執行環境(execution context)

  • 執行環境中包含一個調用對象(call object), 調用對象是一個scriptObject結構(scriptObject是與函數相關的一套靜態系統,與函數實例的生命周期保持一致),用來保存內部變量表varDecls、內嵌函數表funDecls、父級引用列表upvalue等語法分析結構。 varDecls和funDecls等信息是在語法分析階段就已經得到,并保存在語法樹中

  • 函數實例執行時,會將這些信息從語法樹復制到scriptObject上

Executable Code and Execution contents

“執行上下文”可以看做當前代碼的運行環境或者作用域。

Types of Executable Code

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

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

  • Eval Code: 在Eval函數內運行的代碼,在特定的一次對 eval 的調用過程中,eval 代碼作為該程序的 Global Code 部分。

每當調用執行一個函數時,引擎就會自動新建出一個函數上下文, 函數中函數也可能調用另一個函數,這樣又創建一個執行環境, 也被稱為上下文堆棧

執行上下文堆棧

  • ECMAScript的程序執行都可以看做是一個執行上下文堆棧[execution context (EC) stack]。堆棧的頂部就是處于激活狀態的上下文, 堆棧最底部即為全局執行上下文環境[global execution context];

  • 激活其它上下文的某個上下文被稱為 調用者(caller) 。被激活的上下文被稱為被調用者(callee) 。被調用者同時也可能是調用者(比如一個在全局上下文中被調用的函數調用某些自身的內部方法)。

  • 當一個caller激活了一個callee,那么這個caller就會暫停它自身的執行,然后將控制權交給這個callee. 于是這個callee被放入堆棧,稱為進行中的上下文[running/active execution context]. 當這個callee的上下文結束之后,會把控制權再次交給它的caller,然后caller會在剛才暫停的地方繼續執行。在這個caller結束之后,會繼續觸發其他的上下文。一個callee可以用返回(return)或者拋出異常(exception)來結束自身的上下文。

執行上下文的建立過程

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

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

    • 建立變量,函數,arguments對象,參數
    • 建立作用域鏈
    • 確定this的值
  2. 代碼執行階段:

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

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

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

變量對象(variable object)

變量對象(縮寫為VO)是一個與執行上下文相關的特殊對象,它存儲著在上下文中聲明的以下內容:

  1. 變量 (var, 變量聲明)
  2. 函數聲明 (FunctionDeclaration, 縮寫為FD);
  3. 函數的形參 注: 只有全局上下文的變量對象允許通過VO的屬性名稱來間接訪問

不同執行上下文中的變量對象

對于所有類型的執行上下文來說,變量對象的一些操作(如變量初始化)和行為都是共通的。從這個角度來看,把變量對象作為抽象的基本事物來理解更為容易。同樣在函數上下文中也定義和變量對象相關的額外內容。

抽象變量對象VO (變量初始化過程的一般行為)

  1. 全局上下文變量對象GlobalContextVO

    (VO === this === global), VO:

    • 所有函數聲明(FunctionDeclaration, FD)
    • 所有變量聲明(var, VariableDeclaration)
  2. 函數上下文變量對象FunctionContextVO

    (VO === AO, 并且添加了arguments和形參), AO:

    • 普通參數(formal parameters) 與特殊參數(arguments)對象
    • 所有函數聲明(FunctionDeclaration, FD)
    • 所有變量聲明(var, VariableDeclaration)
  3. eval上下文

    • eval會使用全局變量對象或調用者的變量對象(eval的調用來源)
    • 變量聲明在順序上跟在函數聲明和形式參數聲明之后,但不會干擾AO中已經存在的同名函數聲明或形式參數聲明
    • (function x() {}); 類似這樣的函數表達式并不會影響AO
    • 不管是使用var關鍵字(在全局上下文)還是不使用var關鍵字(在任何地方),都可以聲明一個變量”。 請記住,這是錯誤的概念; 任何時候,變量只能通過使用var關鍵字才能聲明。

變量的特性

  1. 變量有一個特性(attribute):{DontDelete},這個特性的含義就是不能用delete操作符直接刪除變量屬性
  2. eval上下文,變量沒有{DontDelete}特性, 使用一些調試工具(例如:Firebug)的控制臺測試該實例時,請注意,Firebug同樣是使用eval來執行控制臺里你的代碼。因此,變量屬性同樣沒有{DontDelete}特性,可以被刪除。

作用域

javascript變量的作用域是在定義時決定而不是執行時決定,也就是說詞法作用域取決于源碼,編譯器通過靜態分析就能確定,因此詞法作用域也叫做靜態作用域(static scope)。但需要注意,with和eval的語義無法僅通過靜態技術實現,所以只能說javascript的作用域機制非常接近詞法作用域(lexical scope)

作用域鏈

在ECMAScript中,會用到內部函數[inner functions],在這些內部函數中,我們可能會引用它的父函數變量,或者全局的變量。我們把這些變量對象成為上下文作用域對象[scope object of the context]. 類似于上面討論的原型鏈[prototype chain],我們在這里稱為作用域鏈[scope chain]

作用域鏈與一個執行上下文相關, 用于在標識符解析中變量查找。 標示符[Identifiers]可以理解為變量名稱、函數聲明和普通參數

函數上下文的作用域鏈在函數調用時創建的,包含活動對象和這個函數內部的[[scope]]屬性。其scope定義如下:Scope = AO + [[Scope]]

函數在被創建時保存外部作用域,是因為這個 被保存的作用域鏈(saved scope chain) 將會在未來的函數調用中用于變量查找。這種形式的作用域稱為靜態作用域[static/lexical scope]

在上下文中示意如下:

activeExecutionContext = {VO: {...}, // or AOthis: thisValue,Scope: [ // Scope chain// 所有變量對象的列表// for identifiers lookup]
};

?

var x = 10;function foo() {alert(x);
}(function () {var x = 20;foo(); // 10, but not 20
})();

  

在標識符解析過程中,使用函數創建時定義的詞法作用域--變量解析為10,而不是20。此外,這個例子也清晰的表明,一個函數(這個例子中為從函數“foo”返回的匿名函數)的[[scope]]持續存在,即使是在函數創建的作用域已經完成之后。

補充說明

  1. 通過構造函數創建的函數的[[scope]]屬性總是唯一的全局對象

  2. 在代碼執行階段有兩個聲明能修改作用域鏈。這就是with聲明和catch語句

  3. 在代碼執行過程中,如果使用with或者catch語句就會改變作用域鏈。而這些對象都是一些簡單對象,他們也會有原型鏈。這樣的話,作用域鏈會從兩個維度來搜尋。

  4. 在解釋執行階段, 遇到變量需要解析時,會首先從當前執行環境的活動對象中查找, 如果沒有找到而且該執行環境擁有者有prototype屬性時, 則會從prototype鏈中查找, 否則將會按照作用域鏈查找;

end!

轉載于:https://www.cnblogs.com/mininice/p/3876307.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259374.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259374.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259374.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

你真的會寫二分檢索嗎?

轉載:http://blog.chinaunix.net/uid-1844931-id-3337784.html 前幾天在論壇上看到有統計說有80%的程序員不能夠寫對簡單的二分法。二分法不是很簡單的嗎? 這難道不是聳人聽聞? 其實,二分法真的不那么簡單,尤其是二…

android listview動態加載網絡圖片不顯示,Android Listview異步動態加載網絡圖片

Android Listview異步動態加載網絡圖片詳見: http://blog.sina.com.cn/s/blog_62186b460100zsvb.html標簽: Android SDK代碼片段(5)[代碼] (1)定義類MapListImageAndText管理ListViewItem中控件的內容01 package com.google.zxing.client.android.AsyncL…

C#-面向對象的多態思想 ---ShinePans

總結: 多態是面向對象的核心.---------能夠理解為一個方法,多種實現, 在這里能夠用虛方法,抽象類,接口能夠實現多態 1.首先利用接口來實現多態: 接口相當于"功能,"接口能夠實現多繼承,分為 顯式實現接口和隱式實現接口 keyword為interface格式: interface 接口名 { …

wxpy 0.1.2微信機器人 / 優雅的微信個人號API

微信機器人 / 優雅的微信個人號API,基于 itchat,全面優化接口,更有 Python 范兒。用來干啥一些常見的場景控制路由器、智能家居等具有開放接口的玩意兒跑腳本時自動把日志發送到你的微信加群主為好友,自動拉進群中跨號或跨群轉發消…

c++中try catch的用法

在c中,可以直接拋出異常之后自己進行捕捉處理,如:(這樣就可以在任何自己得到不想要的結果的時候進行中斷,比如在進行數據庫事務操作的時候,如果某一個語句返回SQL_ERROR則直接拋出異常,在catch塊…

const in c and cpp

http://c-faq.com/ansi/constasconst.html 轉載于:https://www.cnblogs.com/invisible/p/3333575.html

android ndk調用出錯,由于Android-NDK應用程序的權限問題,為什么fopen在本地方法中失敗?...

errno 0;FILE *fp;fp fopen("jigar.txt","wb");if(fp NULL)__android_log_print(ANDROID_LOG_ERROR, APPNAME, "FOPEN FAIL with %d",errno);else__android_log_print(ANDROID_LOG_ERROR, APPNAME, "FOPEN pass ");它得到失敗&…

循環隊列

什么是隊列? 隊列(Queue)也是一種運算受限的線性表。它僅僅同意在表的一端進行插入,而在還有一端進行刪除。同意刪除的一端稱為隊頭(front),同意插入的一端稱為隊尾(rear)。 FIFO原則 隊列具有先進先出原則,與棧的先進后出形成對照…

T(n) = 25T(n/5)+n^2的時間復雜度 計算方法

對于T(n) a*T(n/b)c*n^k;T(1) c 這樣的遞歸關系&#xff0c;有這樣的結論&#xff1a; if (a > b^k) T(n) O(n^(logb(a)));logb(a)b為底a的對數 if (a b^k) T(n) O(n^k*logn); if (a < b^k) T(n) O(n^k); a25; b 5 ; k2 ab^k 故T(n)O(n^k*logn)O(n^2*logn)…

android jar導出,Android項目導出jar包的小技巧

我們知道&#xff0c;可以通過如下設置將一個普通的Android工程轉換成Android Library工程設置前后工程變化如下使用Ant編譯時(通過android.bat update project 命令生成 build.xml)&#xff0c;普通的Android工程會生成apk文件&#xff0c;而Android Library工程只生成jar文件…

(五十九)iOS網絡基礎之UIWebView簡易瀏覽器實現

【UIWebView網絡瀏覽器】 通過webView的loadRequest方法可以發送請求顯示相應的網站&#xff0c;例如&#xff1a; NSURL *url [NSURL URLWithString:"http://m.baidu.com"];// 創建請求數據NSURLRequest *request [NSURLRequest requestWithURL:url];// 向服務器發…

無心插柳OR志在必得?阿里推“來往”的意圖

近年來&#xff0c;阿里巴巴在外圍的動作確實不少&#xff0c;投資新浪微博、投資陌陌&#xff0c;配合阿里自身的一些戰略調整&#xff0c;讓人覺得這家公司似乎正在經歷一場前所未有的“蛻變”。其實這也不難理解&#xff0c;在BAT三國演義中&#xff0c;任何一方都不能對其他…

wampserver的mysql啟動與環境變量設置

安裝好wampserver以后&#xff0c;mysql服務默認已經啟動了。但是直接在命令行里輸入"mysql"&#xff0c;系統會提示說 mysql 不是內部或外部命令&#xff0c;也不是可運行的程序或批處理文件。 這是因為沒有增加“mysql”環境變量,請跳到第3步閱讀。 如果之前已經安…

華為mate30怎么申請鴻蒙內測,華為新系統啟動內測,mate30系列嘗鮮,網友:羨慕...

原標題&#xff1a;華為新系統啟動內測&#xff0c;mate30系列嘗鮮&#xff0c;網友&#xff1a;羨慕一款手機是否好用&#xff0c;其實取決于兩個方面&#xff0c;一個是硬件&#xff0c;另一個則是軟件&#xff0c;大家在購機的時候往往最關注的就是硬件配置&#xff0c;因為…

VMware 11完全安裝Mac OS X 10.10

----------------------------------------- 引用原文如下&#xff1a; VMware 11安裝Mac OS X 10.10_百度經驗 http://jingyan.baidu.com/article/ff411625b9011212e48237b4.html VM11安裝Mac OS X 10.10 工具/原料 1.VMware Workstation 11 2.unlocker 203&#xff08;for OS…

兩個二進制數異或的結果

【面試題目 -亢龍有悔整理】兩個二進制數異或結果是多少? a^b |a-b| (按位相減取絕對值&#xff0c;再按位累加) 兩個二進制數異或結果 是 這兩個二進制數差的絕對值&#xff0c;即表達為如下&#xff1a; a^b |a-b| &#xff08;按位相減取絕對值&#xff0c;再按位累加&am…

Xcode debug時如何查看內存中的數據

對于IPhone開發/XCode的初學者&#xff0c;如何在調試時查看變量的值是很頭痛的事情。因為Xcode的expression 經常無法正確顯示變量的值。但是強大的GDB可以很方便的幫我們查看變量的值。當執行到某斷點時&#xff0c;在GDB窗口中使用po就可以查看變量.(po print object) 1&am…

android另類工具,[置頂] android應用程序開發另解及Android SDK工具集的另類用法

轉載請注明出處&#xff1a;LouisWang http://blog.csdn.net/louiswangbing/article/details/6606865相信對于廣大Android應用開發愛好者來說&#xff0c;Android SDK工具集的大家都已經能夠很熟練的使用&#xff0c;但是我這里要介紹的是SDK工具集的非常用使用方法&#xff0c…

谷歌2007年上交大考試最后一題解答

N個整數&#xff0c;求其中任意N-1個數的乘積中的最大的一個。 例如 3,2,1,則最大的是3*26 提示&#xff1a;整數包括0和負數 要求給出個比較有效率的算法 &#xff0c;不能用除法&#xff0c;只能用乘法。 從網上找一了一個解答比較好&#xff1a;http://bbs.csdn.net/topic…

Dynamic Web Module 3.0 requires Java 1.6 or newer報錯

在項目的pom.xml的<build></build>標簽中加入&#xff1a; <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> &…