日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

js 執(zhí)行上下文和作用域的相關(guān)總結(jié)

瀏覽:211日期:2024-04-05 15:33:52
前言

如果你是或者你想成為一名合格的前端開(kāi)發(fā)工作者,你必須知道JavaScript代碼在執(zhí)行過(guò)程,知道執(zhí)行上下文、作用域、變量提升等相關(guān)概念,并且熟練應(yīng)用到自己的代碼中。本文參考了你不知道的JavaScript,和JavaScript高級(jí)程序設(shè)計(jì),以及部分博客。

正文  1.JavaScript代碼的執(zhí)行過(guò)程相關(guān)概念

js代碼的執(zhí)行分為編譯器的編譯和js引擎與作用域執(zhí)行兩個(gè)階段,其中編譯器編譯的階段(預(yù)編譯階段)分為分詞/詞法分析、解析/語(yǔ)法分析、代碼生成三個(gè)階段。

  (1)在分詞/詞法分析階段,編譯器負(fù)責(zé)將代碼進(jìn)行分割處理,將語(yǔ)句分割成詞法單元流/數(shù)組;

 (2)在解析/詞法分析階段,將上一階段的詞法單元流轉(zhuǎn)換成由元素嵌套組成的符合程序語(yǔ)法結(jié)構(gòu)的抽象語(yǔ)法樹;

  (3)在代碼生成階段,將抽象語(yǔ)法樹轉(zhuǎn)換成可執(zhí)行代碼,并交付給js引擎。

js代碼執(zhí)行的三個(gè)重要角色:

(1)js引擎:負(fù)責(zé)代碼執(zhí)行的整個(gè)過(guò)程

(2)編譯器:負(fù)責(zé)js代碼語(yǔ)法解析和生成可執(zhí)行代碼

(3)作用域:手機(jī)并維護(hù)所有聲明標(biāo)識(shí)符,根據(jù)特定規(guī)則確定當(dāng)前代碼對(duì)聲明的標(biāo)識(shí)符的訪問(wèn)權(quán)限

2. 執(zhí)行上下文和執(zhí)行棧

每當(dāng)js代碼在運(yùn)行的時(shí)候,它都是在執(zhí)行上下文中運(yùn)行。說(shuō)到執(zhí)行上下文,需要知道什么時(shí)執(zhí)行棧,執(zhí)行棧,就是其他編程語(yǔ)言中的“調(diào)用棧”,是一種擁有LIFO(后進(jìn)先出)數(shù)據(jù)結(jié)構(gòu)的棧,被用來(lái)存儲(chǔ)代碼運(yùn)行時(shí)所創(chuàng)建的執(zhí)行上下文。當(dāng)js引擎第一次遇到要執(zhí)行的代碼的時(shí)候,首先會(huì)創(chuàng)建一個(gè)全局的執(zhí)行上下文并壓入當(dāng)前執(zhí)行棧,每當(dāng)引擎遇到一個(gè)函數(shù)調(diào)用,它會(huì)為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文并壓入棧頂,js引擎執(zhí)行棧頂?shù)暮瘮?shù),當(dāng)該函數(shù)執(zhí)行完畢,執(zhí)行上下文從棧中彈出,控制流程到達(dá)下一個(gè)上下文。對(duì)于每一個(gè)執(zhí)行上下文都含有三個(gè)重要屬性:變量對(duì)象,作用域鏈,this。這些屬性也需要徹底理解。

2.1 、上下文調(diào)用棧

var scope1 = 'global scope'; function checkscope1(){ var scope1 = 'local scope'; function f(){ console.log(scope1); } return f(); } checkscope1();

var scope2 = 'global scope'; function checkscope2(){ var scope2 = 'local scope'; function f(){ console.log(scope2); } return f; } checkscope2()();

上面兩段代碼都會(huì)輸出 local scope

  上面代碼中scope一定是局部變量,查找塊級(jí)作用域即可,不管何時(shí)何地執(zhí)行 f(),這種綁定在執(zhí)行f()時(shí)依然有效。出現(xiàn)了一樣的結(jié)果,但是兩段代碼的執(zhí)行上下文棧的變化不一樣 :

第一段代碼:push(<checkscope1>functionContext)=>push(<f>functionContext)=>pop()=>pop()

  第二段代碼:push(<checkscope2>functionContext)=>pop()=>push(<f>functionContext)=>pop()

2.2 、三種執(zhí)行上下文類型

(1)全局上下文

js引擎開(kāi)始解析js代碼的時(shí)候首先遇到的就是全局代碼,初始化的時(shí)候會(huì)在調(diào)用棧中壓入一個(gè)全局執(zhí)行的上下文,當(dāng)整個(gè)應(yīng)用程序結(jié)束的時(shí)候才會(huì)清空?qǐng)?zhí)行上下文棧,棧的最底部永遠(yuǎn)時(shí)全局執(zhí)行上下文。這是默認(rèn)的或者說(shuō)基礎(chǔ)的全局作用域,任何函數(shù)內(nèi)部的代碼都在全局作用域中,首先創(chuàng)建一個(gè)全局的window對(duì)象,然后設(shè)置this的值等于這個(gè)全局對(duì)象,一個(gè)程序中只有一個(gè)全局執(zhí)行上下文。在頂層js代碼中可以使用this引用全局對(duì)象,因?yàn)槿謱?duì)象時(shí)是域鏈的頭,意味著所有非限定性的變量和函數(shù)都作為該對(duì)象的函數(shù)來(lái)查詢。

總之,全局執(zhí)行上下文只有一個(gè),在客戶端中一般由瀏覽器創(chuàng)建,也就是我們熟知的window對(duì)象,我們能通過(guò)this直接訪問(wèn)到它。

(2)函數(shù)上下文

每當(dāng)一個(gè)函數(shù)被調(diào)用是,都會(huì)外該函數(shù)創(chuàng)建一個(gè)新的上下文,每個(gè)函數(shù)都擁有自己的上下文,不過(guò)是在函數(shù)調(diào)用的時(shí)候創(chuàng)建的,需要注意的是同一個(gè)函數(shù)被多次調(diào)用,都會(huì)創(chuàng)建一個(gè)新的上下文。

(3)eval和with上下文

執(zhí)行在 eval和with 函數(shù)內(nèi)部的代碼也會(huì)有它屬于自己的執(zhí)行上下文,但由于 JavaScript 開(kāi)發(fā)者并不經(jīng)常使用 eval,所以在這里我不會(huì)討論它。

2.3 、執(zhí)行上下文創(chuàng)建階段

執(zhí)行上下文創(chuàng)建分為創(chuàng)建階段與執(zhí)行階段兩個(gè)階段

js引擎在執(zhí)行上下文創(chuàng)建階段主要負(fù)責(zé)三件事:確定this==>創(chuàng)建詞法環(huán)境組件==>創(chuàng)建變量環(huán)境組件(目前還不太理解)

(1)確定this,這個(gè)不做詳解

(2)創(chuàng)建詞法環(huán)境組件

詞法環(huán)境是一種規(guī)范類型,基于 ECMAScript 代碼的詞法嵌套結(jié)構(gòu)來(lái)定義標(biāo)識(shí)符和具體變量和函數(shù)的關(guān)聯(lián)。一個(gè)詞法環(huán)境由環(huán)境記錄器和一個(gè)可能的引用外部詞法環(huán)境的空值組成。其中環(huán)境記錄用于存儲(chǔ)當(dāng)前環(huán)境中的變量和函數(shù)聲明的實(shí)際位置;外部環(huán)境引入記錄很好理解,它用于保存自身環(huán)境可以訪問(wèn)的其它外部環(huán)境,那么說(shuō)到這個(gè),是不是有點(diǎn)作用域鏈的意思?

詞法環(huán)境有兩種類型:

全局環(huán)境(在全局執(zhí)行上下文中)是沒(méi)有外部環(huán)境引用的詞法環(huán)境。全局環(huán)境的外部環(huán)境引用是 null。它擁有內(nèi)建的 Object/Array/等、在環(huán)境記錄器內(nèi)的原型函數(shù)(關(guān)聯(lián)全局對(duì)象,比如 window 對(duì)象)還有任何用戶定義的全局變量,并且 this的值指向全局對(duì)象。 在函數(shù)環(huán)境中,函數(shù)內(nèi)部用戶定義的變量存儲(chǔ)在環(huán)境記錄器中。并且引用的外部環(huán)境可能是全局環(huán)境,或者任何包含此內(nèi)部函數(shù)的外部函數(shù)。

(3)創(chuàng)建變量環(huán)境組件

變量環(huán)境可以說(shuō)也是詞法環(huán)境,它具備詞法環(huán)境所有屬性,一樣有環(huán)境記錄與外部環(huán)境引入。在ES6中唯一的區(qū)別在于詞法環(huán)境用于存儲(chǔ)函數(shù)聲明與let const聲明的變量,而變量環(huán)境僅僅存儲(chǔ)var聲明的變量。

3. JavaScript作用域和作用域鏈3.1、作用域

詞法作用域是在寫代碼或者定義的時(shí)候確定的,而動(dòng)態(tài)作用域是在運(yùn)行時(shí)確定的,(this也是)詞法作用域關(guān)注函數(shù)在何處聲明,而動(dòng)態(tài)作用域關(guān)注函數(shù)從何處調(diào)用,JavaScript采用詞法作用域,其作用域由你在寫代碼是將變量和塊作用域?qū)懺谀睦餂Q定,因此當(dāng)詞法分析器處理代碼時(shí)會(huì)保持作用域不變。可以理解為作用域就是一個(gè)獨(dú)立的地盤,讓變量不會(huì)外泄、暴露出去。也就是說(shuō)作用域最大的用處就是隔離變量,不同作用域下同名變量不會(huì)有沖突。

理解作用域之前先來(lái)看一道題

function foo() { console.log(value); } var value = 1; function bar() { var value = 2; console.log(value); foo(); } bar();

上面的代碼會(huì)輸出什么呢,首先在全局上下文中聲明foo()函數(shù)、value變量(其值為undefined)、bar()函數(shù),代碼執(zhí)行階段,bar函數(shù)上下文入棧并執(zhí)行,打印出value為2,然后執(zhí)行foo(),foo()入棧,打印value時(shí)找不到該變量,js引擎會(huì)查找上層作用域,即全局作用域,于是打印出1。后面函數(shù)執(zhí)行完畢上下文出棧。再來(lái)看下面這個(gè)函數(shù),作用域是分層的,內(nèi)層作用域可以訪問(wèn)外層作用域的變量,反之則不行。

js 執(zhí)行上下文和作用域的相關(guān)總結(jié)

ES6以來(lái),js中的作用域分為全局作用域,函數(shù)作用域,塊級(jí)作用域和欺騙作用域。

3.1.1、全局作用域

在代碼中任何地方都能訪問(wèn)到的對(duì)象擁有全局作用域,最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域,所有末定義直接賦值的變量自動(dòng)聲明為擁有全局作用域。

3.1.2、函數(shù)作用域

函數(shù)作用域的含義是指,屬于這個(gè)函數(shù)的全部變量都可以在整個(gè)函數(shù)的范圍內(nèi)使用及復(fù)用(事實(shí)上在嵌套的作用域中也可以使用); 這個(gè)原則是指在軟件設(shè)計(jì)中,應(yīng)該最小限度地暴露必 要內(nèi)容,而將其他內(nèi)容都“隱藏”起來(lái); 函數(shù)表達(dá)式可以是匿名的, 而函數(shù)聲明則不可以省略函數(shù)名。3.1.3、塊作用域塊作用域,通常指 { .. } 內(nèi)部(1)if 、 try/catch創(chuàng)建塊作用域;(2)let 關(guān)鍵字可以將變量綁定到所在的任意作用域中(通常是 { .. } 內(nèi)部);(3)for 循環(huán)頭部的 let 不僅將 i 綁定到了 for 循環(huán)的塊中,事實(shí)上它將其重新綁定到了循環(huán)的每一個(gè)迭代中,確保使用上一個(gè)循環(huán)迭代結(jié)束時(shí)的值重新進(jìn)行賦值;(4)const同樣可以用來(lái)創(chuàng)建塊作用域變量,但其值是固定的 (常量)。創(chuàng)建對(duì)象時(shí)值可以被改變。3.1.4、欺騙詞法作用域的方法,eval()和with() eval()參數(shù)為一個(gè)字符串,并把里面的內(nèi)容當(dāng)作書寫在該位置的代碼一樣處理(非嚴(yán)格模式); with()當(dāng)需要重復(fù)引用一個(gè)對(duì)象的多個(gè)屬性時(shí),可以不需要重復(fù)引用對(duì)象本身。

3.2、作用域鏈

作用域鏈本質(zhì)上就是根據(jù)名稱查找變量(標(biāo)識(shí)符名稱)的一套規(guī)則。規(guī)則非常簡(jiǎn)單,在自己的變量對(duì)象里找不到變量,就上父級(jí)的變量對(duì)象查找,當(dāng)?shù)诌_(dá)最外層的全局上下文中,無(wú)論找到還是沒(méi)找到,查找過(guò)程都會(huì)停止。查找會(huì)在找到第一個(gè)匹配的變量時(shí)停止,被稱為遮蔽效應(yīng)

作用域鏈的用途是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn) 作用域鏈:當(dāng)函數(shù)定義時(shí),系統(tǒng)生成([scope])屬性,該屬性保存該函數(shù)的作用域鏈,該作用域鏈的第0位存儲(chǔ)當(dāng)前環(huán)境下的全局執(zhí)行期上下文GO,GO里存儲(chǔ)全局下的所有對(duì)象,其中包含函數(shù)和全局變量,當(dāng)函數(shù)執(zhí)行的前一刻,預(yù)編譯的時(shí)候,作用域鏈的頂端(第0位)存儲(chǔ)函數(shù)生成的執(zhí)行上下文AO,同時(shí)第一位存儲(chǔ)GO查找變量是到函數(shù)存儲(chǔ)的作用域鏈中從頂端開(kāi)始依次向下查找(函數(shù)內(nèi)部作用域在最頂端,證明了函數(shù)可以訪問(wèn)外部的變量,而外部無(wú)法訪問(wèn)函數(shù)內(nèi)部的變量)

4.執(zhí)行上下文和作用域的區(qū)別

每個(gè)函數(shù)調(diào)用都有與之相關(guān)的作用域和上下文。從根本上說(shuō),范圍是基于函數(shù)(function-based)而上下文是基于對(duì)象(object-based)。換句話說(shuō), 作用域是和每次函數(shù)調(diào)用時(shí)變量的訪問(wèn)有關(guān),并且每次調(diào)用都是獨(dú)立的。上下文總是關(guān)鍵字 this 的值,是調(diào)用當(dāng)前可執(zhí)行代碼的對(duì)象的引用。作用域是函數(shù)定義的時(shí)候就確定好的了,函數(shù)當(dāng)中的變量是和函數(shù)所處的作用域有關(guān),函數(shù)運(yùn)行的作用域也是與該函數(shù)定義時(shí)的作用域有關(guān)。而上下文,主要是關(guān)鍵字this的值,這個(gè)是由函數(shù)運(yùn)行時(shí)決定的,簡(jiǎn)單來(lái)說(shuō)就是誰(shuí)調(diào)用此函數(shù),this就指向誰(shuí)。

5.最后

以上就是js 執(zhí)行上下文和作用域的相關(guān)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于js 執(zhí)行上下文和作用域的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品原创| 91精品蜜臀一区二区三区在线| 成人日韩在线| 色婷婷久久久| 久久精品播放| 伊人成人在线视频| 日韩中文一区二区| 亚洲一区欧美激情| 亚洲二区视频| 日韩精品永久网址| 国产精品a久久久久| 只有精品亚洲| 日韩av一级片| 精品一区二区三区的国产在线观看| 日韩国产在线观看一区| 欧美在线不卡| 亚洲欧洲专区| 91亚洲精品视频在线观看| 国产精选一区| 欧美国产小视频| 国产亚洲一区在线| 欧美在线看片| 成人在线免费观看网站| 狠狠干综合网| 日韩激情网站| 亚洲精品在线影院| 欧美日韩免费观看一区=区三区| 99视频精品视频高清免费| 视频一区免费在线观看| 日本午夜精品久久久久| 日韩电影二区| 欧美啪啪一区| 欧美成人日韩| 久久精品亚洲一区二区| 视频一区免费在线观看| 欧美日韩免费看片| 日韩精品一区二区三区中文在线| 国际精品欧美精品| 免费看日韩精品| 日韩免费一区| 国产精品多人| 在线精品视频一区| 伊人久久国产| 日本va欧美va瓶| 国内精品99| 久久精品国产99国产精品| 国产精品色网| 99精品在线观看| 久久中文字幕一区二区| 日韩成人av影视| 久久国产福利| 欧美特黄一区| 欧美精品一二| 99久久久久| 亚洲午夜天堂| 国产盗摄——sm在线视频| 免费看久久久| 国产精品久久久免费| 日韩高清在线观看一区二区| 午夜视频精品| 免费观看不卡av| 99免费精品| 国产精品91一区二区三区| 视频福利一区| 亚洲91久久| 欧美日韩国产一区二区三区不卡| 麻豆精品蜜桃| 亚洲女同中文字幕| 蜜桃av一区二区三区电影| 亚洲免费专区| 欧美欧美黄在线二区| 国产激情久久| 蜜桃成人精品| 99日韩精品| 日韩中文字幕一区二区三区| 亚洲免费专区| 国产精品黄色片| 超碰成人av| 秋霞国产精品| 精品国产亚洲一区二区三区在线| 麻豆国产精品777777在线| 精品视频亚洲| 宅男噜噜噜66国产日韩在线观看| 一区二区三区国产在线| 国产日韩一区二区三区在线| 国际精品欧美精品| 先锋影音国产一区| 久久不见久久见中文字幕免费| 日韩天堂在线| 91嫩草精品| 精品三区视频| 日韩中文字幕亚洲一区二区va在线| 国产精品夜夜夜| 欧美在线网站| 久久国际精品| 伊人影院久久| 精品无人区麻豆乱码久久久| 欧美不卡高清| 久久久国产精品入口麻豆| 黑丝一区二区三区| 超碰成人av| 国产精品一区二区中文字幕| 美女毛片一区二区三区四区 | 国产成人精品亚洲线观看 | 欧美xxxx中国| 综合激情网...| 五月激情久久| 精品视频久久| 国产精品免费精品自在线观看| 亚洲精品一区二区妖精| 日韩不卡一区| 国产日韩一区二区三区在线| 亚洲欧美不卡| 国产尤物精品| 久久久久久久久丰满| 久久精品三级| 日韩综合小视频| 尤物精品在线| 久久精品av| 久久香蕉国产| 久久九九电影| 天堂а√在线最新版中文在线| 国产精品66| 国产精品久久久久久妇女| 日韩福利在线观看| 日本不卡中文字幕| 日韩一区二区三区精品视频第3页| 国产视频一区欧美| 亚洲免费精品| 丝袜脚交一区二区| 久久香蕉精品| 亚洲综合日本| 免费久久99精品国产自在现线| 欧美91精品| 不卡av一区二区| 免费日韩av片| 日韩制服丝袜av| 日韩在线观看中文字幕| 亚洲欧美在线专区| 欧美一区久久| 欧美极品中文字幕| 精品少妇av| 亚洲午夜在线| 一区二区视频欧美| 中文一区一区三区免费在线观| 中文国产一区| 亚洲一级大片| 中文字幕亚洲影视| 国产欧美欧美| 美女国产精品久久久| 福利一区在线| 在线人成日本视频| 国产综合婷婷| 视频一区免费在线观看| 国产精品一卡| 久久蜜桃精品| 免费观看日韩电影| 91精品国产自产在线丝袜啪| 欧美黄色一区二区| 久久高清免费| 日韩精品一级| 色婷婷久久久| 亚洲乱亚洲高清| 国产成人精选| 中文字幕亚洲影视| 欧美久久天堂| 日韩在线成人| 激情婷婷亚洲| 国产亚洲一卡2卡3卡4卡新区| www.九色在线| 日韩成人精品一区二区三区| 九九精品调教| 国产精品s色| 久久国产精品久久w女人spa| 国产一区2区| 日本一区二区三区中文字幕| 国产成人精品三级高清久久91| 免费不卡中文字幕在线| 欧美国产极品| 日韩精品欧美大片| 在线看片不卡| 亚洲综合电影| 久久不卡日韩美女| 日韩1区2区3区| 日韩视频中文| 国产精品久久久久av电视剧| 国产欧美日韩精品高清二区综合区| 婷婷国产精品| 日韩国产一区| 精品国产不卡| 极品日韩av| 久久国产99| 久久精品一本| 欧美三级第一页| 视频一区二区欧美| 日韩av一级| 国产一区二区三区久久| 欧美一区=区三区| 中文字幕一区二区av| 男女性色大片免费观看一区二区 |