国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

Javascript的詞法作用域分析

2013-03-05 09:53鄧緒高
電腦知識(shí)與技術(shù) 2012年36期

鄧緒高

摘要:在JavaScript中,一個(gè)方法使用的地方和定義的地方有時(shí)會(huì)大相徑庭,在該方法執(zhí)行時(shí),它不能訪(fǎng)問(wèn)哪些變量?可以訪(fǎng)問(wèn)哪些變量?這個(gè)需要怎么判斷呢?這就是該文需要分析的問(wèn)題——詞法作用域。

關(guān)鍵詞:JavaScript;執(zhí)行環(huán)境;活動(dòng)對(duì)象;詞法作用域;閉包

中圖分類(lèi)號(hào):TP271 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2012)36-8663-04

1 JavaScript詞法作用域

JavaScript中詞法作用域指變量的作用域不是執(zhí)行時(shí)決定而是在定義時(shí)決定,也就是說(shuō)通過(guò)靜態(tài)分析就能確定,詞法作用域取決于源碼,因此詞法作用域也叫做靜態(tài)作用域。with和eval除外,所以只能說(shuō)JS的作用域機(jī)制非常接近詞法作用域。

我們可以很快的寫(xiě)出一個(gè)方法,但你可能沒(méi)有進(jìn)行過(guò)深入的學(xué)習(xí)和了解到底方法內(nèi)部是如何執(zhí)行,執(zhí)行的細(xì)節(jié)又是什么。這就需要了解JavaScript引擎的工作方式,才能了解這些細(xì)節(jié),下面我們就把JavaScript引擎對(duì)一個(gè)方法的解析過(guò)程進(jìn)行一個(gè)稍微深入一些的介紹

3 JavaScript方法解析過(guò)程

JavaScript是一種解釋型語(yǔ)言,要開(kāi)始解釋執(zhí)行,得通過(guò)詞法分析和語(yǔ)法分析得到語(yǔ)法分析樹(shù)后才可以。當(dāng)一個(gè)文檔流中包含多個(gè)script代碼段,那么它們的運(yùn)行順序是:

1)讀入第一個(gè)代碼段

2)做詞法分析和語(yǔ)法分析,有錯(cuò)則報(bào)語(yǔ)法錯(cuò)誤,并跳轉(zhuǎn)到步驟5

3)對(duì)var變量和function定義做“預(yù)解析“

4)執(zhí)行代碼段,有錯(cuò)則報(bào)錯(cuò)

5)如果還有下一個(gè)代碼段,則讀入下一個(gè)代碼段,重復(fù)步驟2

6)結(jié)束

3.1 特殊說(shuō)明

全局域(window)域下所有JavaScript代碼會(huì)被自動(dòng)執(zhí)行,可以被看成是一個(gè)“匿名方法“,而此“匿名方法“內(nèi)的其它方法則是在被顯示調(diào)用的時(shí)候才被執(zhí)行。

3.2 關(guān)鍵步驟

上面的過(guò)程,我們主要是分成兩個(gè)階段

1)解析:就是通過(guò)語(yǔ)法分析和預(yù)解析構(gòu)造合法的語(yǔ)法分析樹(shù)。

2)執(zhí)行:執(zhí)行具體的某個(gè)function,JavaScript引擎在執(zhí)行每個(gè)函數(shù)實(shí)例時(shí),都會(huì)創(chuàng)建一個(gè)執(zhí)行環(huán)境(ExecutionContext)和活動(dòng)對(duì)象(activeObject)。

3.3 關(guān)鍵概念

到這里,我們?cè)俑鼜?qiáng)調(diào)以下一些概念,這些概念都會(huì)在下面用一個(gè)一個(gè)的實(shí)體來(lái)表示,便于大家理解

1)語(yǔ)法分析樹(shù)(SyntaxTree)可以直觀地表示出這段代碼的相關(guān)信息,具體的實(shí)現(xiàn)就是JavaScript引擎創(chuàng)建了一些表,用來(lái)記錄每個(gè)方法內(nèi)的變量集(variables),方法集(functions)和作用域(scope)等

2)執(zhí)行環(huán)境(ExecutionContext)可理解為一個(gè)記錄當(dāng)前執(zhí)行的方法(外部描述信息)的對(duì)象,記錄所執(zhí)行方法的類(lèi)型,名稱(chēng),參數(shù)和活動(dòng)對(duì)象(activeObject)

3)活動(dòng)對(duì)象(activeObject)可理解為一個(gè)記錄當(dāng)前執(zhí)行的方法(內(nèi)部執(zhí)行信息)的對(duì)象,記錄內(nèi)部變量集(variables)、內(nèi)嵌函數(shù)集(functions)、實(shí)參(arguments)、作用域鏈(scopeChain)等執(zhí)行所需信息,其中內(nèi)部變量集(variables)、內(nèi)嵌函數(shù)集(functions)是直接從第一步建立的語(yǔ)法分析樹(shù)復(fù)制過(guò)來(lái)的

上面就是關(guān)于語(yǔ)法分析樹(shù)的一個(gè)簡(jiǎn)單表示,正如我們前面分析的,語(yǔ)法分析樹(shù)主要記錄了每個(gè) function中的變量集(variables),方法集(functions)和作用域(scope)。以下是語(yǔ)法分析樹(shù)關(guān)鍵點(diǎn):

1)變量集(variables)中,只有變量定義,沒(méi)有變量值,這時(shí)候的變量值全部為“undefined”

2)作用域(scope),根據(jù)詞法作用域的特點(diǎn),這個(gè)時(shí)候每個(gè)變量的作用域就已經(jīng)明確了,而不會(huì)隨執(zhí)行時(shí)的環(huán)境而改變。

3)作用域(scope)建立規(guī)則

a) 對(duì)于函數(shù)聲明和匿名函數(shù)表達(dá)式來(lái)說(shuō),[scope]就是它創(chuàng)建時(shí)的作用域

b) 對(duì)于有名字的函數(shù)表達(dá)式,[scope]頂端是一個(gè)新的JavaScript對(duì)象(也就是繼承了Object.prototype),這個(gè)對(duì)象有兩個(gè)屬性,第一個(gè)是自身的名稱(chēng),第二個(gè)是定義的作用域,第一個(gè)函數(shù)名稱(chēng)是為了確保函數(shù)內(nèi)部的代碼可以無(wú)誤地訪(fǎng)問(wèn)自己的函數(shù)名進(jìn)行遞歸。

4.2 執(zhí)行環(huán)境與活動(dòng)對(duì)象

語(yǔ)法分析完成,開(kāi)始執(zhí)行代碼。我們調(diào)用每一個(gè)方法的時(shí)候,JavaScript引擎都會(huì)自動(dòng)為其建立一個(gè)執(zhí)行環(huán)境和一個(gè)活動(dòng)對(duì)象,它們和方法實(shí)例的生命周期保持一致,為方法執(zhí)行提供必要的執(zhí)行支持,針對(duì)上面的幾個(gè)方法,我們這里統(tǒng)一為其建立了活動(dòng)對(duì)象,具體如下:

上面每一個(gè)活動(dòng)對(duì)象都存儲(chǔ)了相應(yīng)方法的內(nèi)部變量集(variables)、內(nèi)嵌函數(shù)集(functions)、形參(parameters)、實(shí)參(arguments)等執(zhí)行所需信息?;顒?dòng)對(duì)象關(guān)鍵點(diǎn)如下:

1) 創(chuàng)建活動(dòng)對(duì)象,從語(yǔ)法分析樹(shù)復(fù)制方法的內(nèi)部變量集(variables)和內(nèi)嵌函數(shù)集(functions)

2) 方法開(kāi)始執(zhí)行,活動(dòng)對(duì)象里的內(nèi)部變量集全部被重置為 undefined

3) 創(chuàng)建形參(parameters)和實(shí)參(arguments)對(duì)象,同名的實(shí)參,形參和變量之間是【引用】關(guān)系

4) 執(zhí)行方法內(nèi)的賦值語(yǔ)句,這才會(huì)對(duì)變量集中的變量進(jìn)行賦值處理

5) 變量查找規(guī)則是首先在當(dāng)前執(zhí)行環(huán)境的activeObject中尋找,沒(méi)找到,則順著執(zhí)行環(huán)境中屬性scopeChain指向的activeObject中尋找,一直到Global Object(window)

6) 方法執(zhí)行完成后,內(nèi)部變量值不會(huì)被重置,至于變量什么時(shí)候被銷(xiāo)毀,請(qǐng)參考下面一條

7) 方法內(nèi)變量的生存周期取決于方法實(shí)例是否存在活動(dòng)引用,如沒(méi)有就銷(xiāo)毀活動(dòng)對(duì)象

8) 步驟f和g是使閉包能訪(fǎng)問(wèn)到外部變量的根本原因

5 重釋經(jīng)典案例

在案列一中,由于在一個(gè)方法中,同名的實(shí)參,形參和變量之間是引用關(guān)系,也就是說(shuō)JavaScript引擎的處理是同名變量和形參都引用同一個(gè)內(nèi)存地址,所以在二中的修改arguments才會(huì)有影響到局部變量的這種情況出現(xiàn)。

在案例二中,根據(jù)JavaScript引擎變量查找規(guī)則,在當(dāng)前執(zhí)行環(huán)境的ActiveObject中尋找,未果,則順著執(zhí)行環(huán)境中屬性ScopeChain指向的ActiveObject中尋找,一直到GlobalObject(window),所以在四中,因?yàn)樵诋?dāng)前的ActiveObject中找到了有變量i的定義,只是值為“undefined”,所以直接輸出“undefined”了

6 總結(jié)

以上是我在學(xué)習(xí)和使用了JavaScript一段時(shí)間后,為了更深入的了解JavaScript,也為了更好的把握對(duì)JavaScript的應(yīng)用,從而在對(duì)閉包的學(xué)習(xí)過(guò)程中,自己對(duì)于詞法作用域的一些總結(jié)和理解,中間可能有一些地方不同于真實(shí)的JavaScript解釋引擎,因?yàn)槲也皇钦驹谝粋€(gè)系統(tǒng)設(shè)計(jì)者的角度而是站在一個(gè)剛?cè)腴T(mén)的前端開(kāi)發(fā)人員的角度上去分析這個(gè)問(wèn)題,希望能對(duì)JavaScript開(kāi)發(fā)者理解詞法作用域帶來(lái)一些幫助!

參考文獻(xiàn):

[1] 弗蘭納根.JavaScript權(quán)威指南[M].6版.北京:機(jī)械工業(yè)出版社,2012.

[2] Nicholas C,Zakas.JavaScript高級(jí)程序設(shè)計(jì)[M].3版.北京:人民郵電出版社,2012.

[3] Stephen.淺談JavaScript的閉包和作用域鏈[EB/OL]. (2010-01-20).http://blog.endlesscode.com/2010/01/20/javascript-closure-scope-chain/447/1865447.shtml.

定西市| 竹山县| 彝良县| 汽车| 雅江县| 洞口县| 永清县| 县级市| 交城县| 浦江县| 罗田县| 宁南县| 清苑县| 望江县| 甘南县| 桦川县| 苏州市| 左权县| 晋城| 澄城县| 平果县| 鹤山市| 武胜县| 滁州市| 鄯善县| 巴林右旗| 延长县| 韶关市| 离岛区| 沂水县| 涞水县| 拉萨市| 龙胜| 伊金霍洛旗| 子长县| 惠东县| 布尔津县| 六安市| 桐乡市| 泰宁县| 静海县|