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

您的位置:首頁技術文章
文章詳情頁

Javascript作用域和作用域鏈原理解析

瀏覽:195日期:2023-11-09 10:21:26

作用域和作用域鏈在Javascript和很多其它的編程語言中都是一種基礎概念。但很多Javascript開發者并不真正理解它們,但這些概念對掌握Javascript至關重要。

正確的去理解這個概念有利于你去寫更好,更高效和更簡潔的代碼,讓你成為一個更優秀的Javascript開發者。

因此,在本文中,我將會向大家解釋清楚什么是作用域和作用域鏈,以及Javascript引擎在內部是如何通過它們操作和查找變量的。

事不宜遲,正文開始 :)

什么是作用域

Javascript中的作用域說的是變量的可訪問性和可見性。也就是說整個程序中哪些部分可以訪問這個變量,或者說這個變量都在哪些地方可見。

為什么作用域很重要

作用域最為重要的一點是安全。變量只能在特定的區域內才能被訪問,有了作用域我們就可以避免在程序其它位置意外對某個變量做出修改。

作用域也會減輕命名的壓力。我們可以在不同的作用域下面定義相同的變量名。

作用域的類型

Javascript中有三種作用域:

全局作用域; 函數作用域; 塊級作用域;

1. 全局作用域

任何不在函數中或是大括號中聲明的變量,都是在全局作用域下,全局作用域下聲明的變量可以在程序的任意位置訪問。例如:

// 全局變量var greeting = ’Hello World!’;function greet() { console.log(greeting);}// 打印 ’Hello World!’greet();

2. 函數作用域

函數作用域也叫局部作用域,如果一個變量是在函數內部聲明的它就在一個函數作用域下面。這些變量只能在函數內部訪問,不能在函數以外去訪問。例如:

function greet() { var greeting = ’Hello World!’; console.log(greeting);}// 打印 ’Hello World!’greet();// 報錯: Uncaught ReferenceError: greeting is not definedconsole.log(greeting);

3. 塊級作用域

ES6引入了let和const關鍵字,和var關鍵字不同,在大括號中使用let和const聲明的變量存在于塊級作用域中。在大括號之外不能訪問這些變量。看例子:

{ // 塊級作用域中的變量 let greeting = ’Hello World!’; var lang = ’English’; console.log(greeting); // Prints ’Hello World!’}// 變量 ’English’console.log(lang);// 報錯:Uncaught ReferenceError: greeting is not definedconsole.log(greeting);

上面代碼中可以看出,在大括號內使用var聲明的變量lang是可以在大括號之外訪問的。使用var聲明的變量不存在塊級作用域中。

作用域嵌套

像Javascript中函數可以在一個函數內部聲明另一個函數一樣,作用域也可以嵌套在另一個作用域中。請看例子:

var name = ’Peter’;function greet() { var greeting = ’Hello’; { let lang = ’English’; console.log(`${lang}: ${greeting} ${name}`); }}greet();

這里我們有三層作用域嵌套,首先第一層是一個塊級作用域(let聲明的),被嵌套在一個函數作用域(greet函數)中,最外層作用域是全局作用域。

詞法作用域

詞法作用域(也叫靜態作用域)從字面意義上看是說作用域在詞法化階段(通常是編譯階段)確定而非執行階段確定的??蠢樱?/p>

let number = 42;function printNumber() { console.log(number);}function log() { let number = 54; printNumber();}// Prints 42log();

上面代碼可以看出無論printNumber()在哪里調用console.log(number)都會打印42。動態作用域不同,console.log(number)這行代碼打印什么取決于函數printNumber()在哪里調用。

如果是動態作用域,上面console.log(number)這行代碼就會打印54。

使用詞法作用域,我們可以僅僅看源代碼就可以確定一個變量的作用范圍,但如果是動態作用域,代碼執行之前我們沒法確定變量的作用范圍。

像C,C++,Java,Javascript等大多數編程語言都支持靜態作用域。Perl 既支持動態作用域也支持靜態作用域。

作用域鏈

當在Javascript中使用一個變量的時候,首先Javascript引擎會嘗試在當前作用域下去尋找該變量,如果沒找到,再到它的上層作用域尋找,以此類推直到找到該變量或是已經到了全局作用域。

如果在全局作用域里仍然找不到該變量,它就會在全局范圍內隱式聲明該變量(非嚴格模式下)或是直接報錯。

例如:

let foo = ’foo’;function bar() { let baz = ’baz’; // 打印 ’baz’ console.log(baz); // 打印 ’foo’ console.log(foo); number = 42; console.log(number); // 打印 42}bar();

當函數bar()被調用,Javascript引擎首先在當前作用域下尋找變量baz,然后尋找foo變量但發現在當前作用域下找不到,然后繼續在外部作用域尋找找到了它(這里是在全局作用域找到的)。

然后將42賦值給變量number。Javascript引擎會在當前作用域以及外部作用域下一步步尋找number變量(沒找到)。

如果是在非嚴格模式下,引擎會創建一個number的全局變量并把42賦值給它。但如果是嚴格模式下就會報錯了。

結論:當使用一個變量的時候,Javascript引擎會循著作用域鏈一層一層往上找該變量,直到找到該變量為止。

作用域和作用域鏈是如何工作的

以上內容已經講解了作用域,作用域的類型,現在讓我們看下Javascript引擎是如何確定變量的作用域鏈和如何去查找變量的。

要想理解Javascript是如何進行變量查找的,必須要了解Javascript中詞法環境這個概念(請參考:理解Javascript中的執行上下文和執行棧)。

什么是詞法環境

所謂詞法環境就是一種標識符—變量映射的結構(這里的標識符指的是變量/函數的名字,變量是對實際對象[包含函數和數組類型的對象]或基礎數據類型的引用)。

簡單地說,詞法環境是Javascript引擎用來存儲變量和對象引用的地方。

注意:不要混淆了詞法環境和詞法作用域,詞法作用域是在代碼編譯階段確定的作用域(譯者注:一個抽象的概念),而詞法環境是Javascript引擎用來存儲變量和對象引用的地方(譯者注:一個具象的概念)。

一個詞法環境就像下面這樣:

lexicalEnvironment = { a: 25, obj: <ref. to the object>}

只有當該作用域的代碼被執行的時候,引擎才會為那個作用域創建一個新的詞法環境。詞法環境還會記錄所引用的外部詞法環境(即外部作用域)。例:

lexicalEnvironment = { a: 25, obj: <ref. to the object> outer: <outer lexical environemt>}

Javascript引擎是如何進行變量查找的

現在我們已經知道了作用域,作用域鏈和詞法環境的概念,現在讓我們看下Javascript引擎是如何利用詞法環境來確定作用域和作用域鏈的。

結合例子我們來理解上面的這些概念:

let greeting = ’Hello’;function greet() { let name = ’Peter’; console.log(`${greeting} ${name}`); // Hello Peter}greet();{ let greeting = ’Hello World!’ console.log(greeting); // Hello World!}

上述代碼加載后,首先會創建一個全局詞法環境,其中包含在全局范圍內聲明的變量和函數。像下面這樣:

globalLexicalEnvironment = { greeting: ’Hello’ greet: <ref. to greet function> outer: <null>}

這里的outer字段(也就是外部詞法環境)被設置為了null,是因為全局詞法環境已經是最頂層的詞法環境了。

然后,我們調用了greet()函數,然后一個新的詞法環境會被被創建:

functionLexicalEnvironment = { name: ’Peter’ outer: <globalLexicalEnvironment>}

這里的outer字段被設置為了globalLexicalEnvironment,是因為他的外部作用域就是全局作用域。

然后,執行console.log(`${greeting} ${name}`)這行代碼,Javascript引擎首先在當前函數的詞法環境中尋找變量greeting和name,但只找到了name,沒找到greeting。然后繼續在上層的詞法環境中找greeting(這里是全局作詞法環境)。最后在全局詞法環境中找到了greeting。

緊接著執行那段在大括號里的代碼,為這個塊級創建一個新的詞法環境。如下:

blockLexicalEnvironment = { greeting: ’Hello World’, outer: <globalLexicalEnvironment>}

然后執行console.log(greeting)這行代碼,首先在本層詞法環境中找greeting,OK,找到,結束。此時就不會再去外部作用域(這里是全局作用域)尋找該變量了。

注意:只有let和const聲明變量才會創建一個新的詞法環境存儲,使用var聲明的變量會被存儲在當前塊(大括號)所在的詞法環境中(全局詞法環境或是函數詞法環境中)。

結論:當一個變量被使用時,Javascript引擎會首先在當前的詞法環境中進行尋找,如果找不到就找上層詞法環境中尋找,直到找到為止。

結論

作用域就是一個變量可訪問和可見的區域,和函數一樣,Javascript的作用域也可以嵌套,Javascript引擎會層層遍歷作用域來尋找用到的變量。

Javascript使用詞法作用域,這意味著變量的作用在編譯階段就會被確定。

Javascript引擎在程序執行期間使用詞法環境來存儲變量和函數。

作用域和作用域鏈是Javascript中的基礎概念,理解作用域和作用域鏈能讓你成為一個更優秀的Javascript開發者。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: JavaScript
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国际精品欧美精品| 日韩一区二区三免费高清在线观看 | 色老板在线视频一区二区| 国精品产品一区| 成人污污视频| 97精品国产福利一区二区三区| 久久99精品久久久久久园产越南| 欧美一区二区三区免费看| 日本成人中文字幕在线视频| 国产精品一区二区三区美女| 精品久久美女| 自由日本语亚洲人高潮| 在线看片日韩| 老司机精品视频网| 麻豆精品蜜桃| 亚洲+小说+欧美+激情+另类| 日本欧美大码aⅴ在线播放| 国产精品地址| 国产精品99一区二区| 美国三级日本三级久久99| 涩涩涩久久久成人精品| 美女久久久精品| 中文在线不卡| 欧美经典一区| 美女久久一区| 久久久久久夜| 日韩综合一区二区| 老牛影视精品| 日韩激情啪啪| 99国内精品| 91亚洲一区| 日韩av在线播放中文字幕| 成年男女免费视频网站不卡| 在线国产日韩| 欧美日韩在线二区| 欧美啪啪一区| 婷婷综合在线| 黄色aa久久| 欧美激情久久久久久久久久久| 老司机久久99久久精品播放免费| а√在线中文在线新版| 日韩av电影一区| 免费久久精品视频| japanese国产精品| 在线天堂中文资源最新版| 日韩精品社区| 免费人成在线不卡| 亚洲综合日韩| 久久福利一区| 欧美精品一线| 日韩精品一区二区三区免费观影 | 国产韩日影视精品| 综合日韩av| 国产精品久久久久久久久久10秀 | 91成人在线精品视频| 综合五月婷婷| 免费观看在线综合色| 久久亚洲美女| 亚洲欧洲一区| 亚洲色诱最新| 亚洲1区在线| 国产日产高清欧美一区二区三区| 日韩精品亚洲专区在线观看| 日韩中文字幕| 国产区精品区| 精品网站999| а√天堂中文在线资源8| 日韩三区免费| 久久精品一区二区不卡| 香蕉久久99| 国产精品毛片| 欧美日韩a区| 97在线精品| 久久久影院免费| 免费看欧美美女黄的网站| 欧美日韩在线精品一区二区三区激情综合 | 欧美激情aⅴ一区二区三区| 国产成人精品亚洲线观看| 日本韩国欧美超级黄在线观看| 伊人久久大香线蕉av超碰演员| 亚洲视频电影在线| 日本欧美一区二区| av资源中文在线天堂| 欧美高清不卡| 国产九一精品| 97国产成人高清在线观看| 99亚洲视频| 国产精品2023| 亚洲高清影视| 国产伦精品一区二区三区千人斩| 免费高潮视频95在线观看网站| 美女精品在线观看| 高清一区二区三区av| 丝袜脚交一区二区| 亚洲精品**中文毛片| 天堂va在线高清一区| 久久在线免费| 精品国产不卡一区二区| 亚洲精品九九| 五月婷婷六月综合| 你懂的网址国产 欧美| 久久香蕉精品| 99热国内精品| 精品国产亚洲一区二区三区大结局| 欧美成人国产| 97精品97| 国产专区精品| 国产精品1区| 欧美欧美黄在线二区| 综合激情一区| 另类国产ts人妖高潮视频| 色老板在线视频一区二区| 国产成人精选| 成人综合一区| 亚洲午夜天堂| 久久成人福利| 国产伦乱精品| 免费在线日韩av| 国产精品亚洲片在线播放| 日韩高清二区| 欧美一级网站| 国产精品magnet| 你懂的亚洲视频| 国产在线一区不卡| 福利一区和二区| 四虎国产精品免费观看| 精品久久精品| 日韩精品欧美| 国产精品91一区二区三区| 久久久一二三| 国产91久久精品一区二区| 香蕉人人精品| 男女男精品视频网| 日本不卡不码高清免费观看| 欧美有码在线| 精品免费视频| 久久国产中文字幕| 亚洲综合福利| 久久久久久久久成人| 日韩在线短视频| 三级欧美韩日大片在线看| 日韩高清电影免费| 91日韩欧美| 在线综合亚洲| 麻豆极品一区二区三区| 日韩欧美精品一区| 亚洲在线一区| 麻豆久久一区二区| 好看的av在线不卡观看| 国产一精品一av一免费爽爽| 国产一区二区视频在线看| 蜜臀久久99精品久久一区二区| 视频一区国产视频| 国产成人1区| 视频一区视频二区在线观看| 久久香蕉网站| 喷白浆一区二区| 特黄毛片在线观看| 日本不卡一区二区三区| 深夜视频一区二区| 亚洲精品乱码日韩| 国产拍在线视频| 日韩中文字幕| 欧美日韩精品免费观看视频完整| 国产日韩欧美在线播放不卡| 亚洲大片在线| 久久99国产精品视频| 爽爽淫人综合网网站| 天堂日韩电影| 免费看一区二区三区| 中文字幕亚洲影视| 欧美日韩第一| 波多野结衣久久精品| 国产精品porn| 国产精品一区二区三区四区在线观看| 欧美成a人免费观看久久| 国产精品大片| 久久激情综合网| 亚洲香蕉视频| 香蕉成人久久| 亚洲激情社区| 999精品在线| 免费福利视频一区二区三区| 精品视频自拍| 韩国女主播一区二区三区| 欧美激情久久久久久久久久久| 91福利精品在线观看| 日韩精品午夜视频| 日韩精品三级| 国产欧美日韩影院| 日韩高清不卡一区| 日韩福利视频一区| 日韩av一级片| 久久国产婷婷国产香蕉| 91国内精品| 鲁大师精品99久久久| 精品美女视频 | 亚洲三区欧美一区国产二区| 日韩中文字幕亚洲一区二区va在线| 日韩一区二区免费看|