亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

通過JS運行機制的角度說說作用域

2024-05-06 16:48:58
字體:
來源:轉載
供稿:網友

前言

任何程序設計語言都有作用域的概念,簡單的說,作用域就是變量與函數的可訪問范圍。JS中的作用域、閉包、this機制和原型往往是最難理解的概念之一。筆者將通過幾篇文章和大家談談自己的理解,希望對大家的學習有一些幫助。如果有什么理解偏差的地方,希望大家可以評論指出,相互學習。

有過一定編程經驗的同學,一定不會對作用域感到陌生,在C/C++/Java中等語言中,作用域從來沒有JavaScript中的作用域那樣令人困惑以致于成為一個大多數JS開發者都難以跨過的門檻。

作用域形成機制

JS中存在的三種作用域類型:全局作用域,函數作用域和ES6中新加入的塊級作用域。

var a = 1;function foo() { var b = 2; console.log(a);		// 1 console.log(b);		// 2 console.log(c);		// ReferenceError}function foo1() { var c = 3; console.log(a);		// 1 console.log(b);		// ReferenceError console.log(c);		// 3}console.log(a);			// 1console.log(b); 		// ReferenceErrorconsole.log(c);			// ReferenceErrorfoo();foo1();

從上面的例子可以看到,每個函數內部形成了屬于自己的作用域,函數內部聲明的變量僅僅在定義的函數內部才可以訪問。全局作用域中可以訪問到的有a,foo,foo作用域中可以訪問到的有b,foo,a,foo1的作用域中可以訪問到的有c,foo,a。因為foo的作用域嵌套在全局作用域之中,當console.log(a);執行的時候,JS在foo的作用域查找不到a,就會到它的上層(這里是foo的上層直接就是全局作用域)查找,發現這里聲明了一個a,將它的值打印了出來。這種從里到外的查找就是根據作用域鏈查找。foo1和foo的作用域沒有嵌套關系,所以相互隔離。

如果函數中使用了未聲明的變量怎么辦?

function foo() {	a = 2;}foo();console.log(a);		// 2

JS引擎在foo中查找不到a的聲明,便會到它的上層(這里是全局作用域中)查找,這個時候還是沒有查找到a的聲明,在非嚴格模式下,JS引擎會在全局中自動聲明一個a,這個時候,未經聲明的變量a實際上泄漏到了全局作用域中。

只有使用未聲明的變量才會出現變量泄漏的問題么,其實,不僅僅這種寫法會出現,更常見的也會出現在for循環和if代碼塊中也會出現。

for(var i=1;i<10;i++) { console.log(i);}console.log(i);		// 10,	這里的i泄漏到了全局作用域中if(true) { var a = 2;}console.log(a);		// 2, 這里的a也泄漏到了全局變量之中

如果你學習過C語言系列的語法,往往很容易感到困惑,if和for居然沒有作用域,這真是太奇怪了。這一切的問題的根源,都是由于ES6之前沒有塊級作用域導致的。所以可想而知,if包裹的代碼塊,同樣里面的聲明也是暴露出來的~

一切問題的解決直到ES6中引入了let和const得以完美的解決。使用let和const,將可以使用塊級作用域,使得聲明變量泄漏的問題得以解決。

for(let i=1;i<10;i++) { console.log(i);}console.log(i);		// ReferenceErrorif(true) { let a = 2;}console.log(a);		// ReferenceError

聲明提升機制

對于在JS中聲明的不論是變量還是函數,基本上都會存在著變量聲明提升的行為,將變量的聲明提升到所在作用域的頂端。ES6中的let和const不會,在未聲明之前都不可以使用。

看看下面的代碼

console.log(a);				// undefinedconsole.log(b);				// undefinedconsole.log(foo);			// Functionconsole.log(foo2);		// ReferenceErrorfunction foo () { console.log('聲明提升了哈');}var a = 1;var b = function foo2() { console.log('不同的函數聲明方式提升的結果也不一樣哦');};

JS 引擎解釋這段代碼之前首先對代碼中所有的變量進行了聲明的提升,函數聲明的提升的優先級是高于普通變量的,函數聲明會整個提升到所在作用域的頂端(但是以函數表達式方式聲明的函數不會),代碼實際上是下面這個樣子:

function foo () { console.log('聲明提升了哈');}var a;var b;var foo2;console.log(a);console.log(b);console.log(foo);console.log(foo2);b = function foo2 () { console.log('不同的函數聲明方式提升的結果也不一樣哦');}

靜態作用域機制(詞法作用域)

關于JS中的作用域,需要明確的一點就是,JS中只存在靜態作用域(詞法作用域)。靜態作用域是什么意思呢?意思就是它的作用域在你寫下代碼的時候就已經確定了,和函數的調用順序無關,了解這一點。就可以對一些常見的現象進行解釋。

var a = 2;function foo() { console.log(a);}var obj = { a: 3, foo: foo}obj.foo();		// 2

foo中的a在代碼寫完時就確認了,指向了全局作用域中的a,一旦確定就無法更改了。同理,下面的代碼

function foo() { console.log(b);			// ReferenceError}function foo1 () { var b = 1; foo();}foo1();

這里,JS引擎在全局作用域中查找不到b,所以會拋出一個異常。所以可以明確的道理是,foo的作用域和foo1的作用域仍然是相互獨立的,不會因為調用時候的順序而更改作用域的嵌套順序,靜態作用域在代碼書寫時就已經確定無法更改了,明白這一點在分析JS代碼的時候尤為重要。

坑外話

變量的遮蔽效應

在函數中定義的變量會遮蔽上層作用域中同名的變量,兩個變量互不影響。

var a = 1;function foo() { var a = 2; console.log(a);	// 2}console.log(a);		// 1

Try-Catch 中的塊級作用域

try-catch的catch中會創建一個塊級作用域,該作用域內變量的表現同樣遵守變量的聲明提升規則。

try { throw undefined;}catch(e) { a = 1; console.log(e);		// undefined}console.log(a);			// 1,	變量提升規則console.log(e);			// ReferenceError,catch的塊作用域中定義的變量

隱式聲明

以參數形式傳入的變量在函數內部實際上存在的隱式的聲明,使用時不算作未聲明的變量。

function foo(a) { a = 1; console.log(a);}foo();						// 1console.log(a);		// ReferenceError

本來想一篇文章寫完作用域和閉包的,想例子實在是累,就拆作兩篇吧,逃~

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品一区二区久久| 91国内产香蕉| 日韩在线观看免费网站| 亚洲xxxx妇黄裸体| 91久久国产婷婷一区二区| 91成人福利在线| 中文字幕av一区二区三区谷原希美| 日韩av在线免费看| 亚洲午夜久久久久久久| 欧美影院成年免费版| 国产aⅴ夜夜欢一区二区三区| 亚洲成人激情视频| 国产精品白丝av嫩草影院| 欧美日韩精品在线视频| 国产欧美精品日韩| 久久视频在线免费观看| 在线成人中文字幕| 国产一区二区日韩精品欧美精品| 欧美激情一区二区三级高清视频| 中文字幕亚洲无线码在线一区| 色综合色综合网色综合| 欧美劲爆第一页| 午夜精品视频在线| 日韩精品福利网站| 久久久精品电影| www.亚洲男人天堂| 日韩在线观看精品| 日韩免费高清在线观看| 青青草成人在线| 日韩精品在线免费| 国产精品久久久久免费a∨| 国产精品∨欧美精品v日韩精品| 日本一区二区在线免费播放| 国产成人亚洲综合91| 亚洲一级黄色片| 亚洲免费伊人电影在线观看av| 精品国产老师黑色丝袜高跟鞋| 亚洲精品成人av| 91久久久久久久久| 国产精品18久久久久久首页狼| 国产日韩中文字幕| 久久久国产成人精品| 亚洲午夜未删减在线观看| 欧美激情在线狂野欧美精品| 欧美久久久精品| 秋霞成人午夜鲁丝一区二区三区| 精品国内亚洲在观看18黄| 国产成人在线一区二区| 国产91精品久久久久| 欧美激情一区二区久久久| 国产午夜一区二区| 九九久久国产精品| 日韩中文字幕av| 国产精欧美一区二区三区| 久久久久久久网站| 亚洲国产精品高清久久久| 亚洲最大成人免费视频| 色综合久久久888| 国内精品久久久久久中文字幕| 欲色天天网综合久久| 日韩欧美国产免费播放| 精品久久中文字幕| 久久精品国产视频| 精品久久久一区二区| 国产精品网红直播| 人九九综合九九宗合| 日韩在线中文视频| 国产精品久久999| 国产精品爽爽ⅴa在线观看| 91精品国产高清久久久久久91| 国产精品视频大全| 欧美亚洲日本黄色| 精品国产91久久久久久| 日本精品一区二区三区在线| 视频在线观看一区二区| 国产精品爽黄69天堂a| 欧美亚洲在线视频| 亚洲人av在线影院| 欧美电影在线播放| 久久久久久97| 日韩中文字幕av| 国产精品久久久久99| 国产精品福利观看| 欧美一区二区大胆人体摄影专业网站| 国产91成人在在线播放| 精品久久久久久国产91| 美女久久久久久久| 国产欧美婷婷中文| 亚洲成人精品在线| 黄色精品一区二区| 久久综合伊人77777蜜臀| 欧美成人一二三| 欧美性猛交xxxx乱大交极品| 这里只有视频精品| 久久久久999| 亚洲精品一区中文字幕乱码| 九九热这里只有精品免费看| 久久99视频免费| 一本色道久久综合狠狠躁篇怎么玩| 国产ts一区二区| 中文字幕精品www乱入免费视频| 国产精品久久久久久久美男| 伊人久久久久久久久久| 97久久久免费福利网址| 亚洲中国色老太| 欧美在线视频观看免费网站| 国产精品久久久久久久久久尿| 亚洲午夜av久久乱码| 亚洲精品日韩久久久| 91在线观看免费高清完整版在线观看| 欲色天天网综合久久| 精品亚洲永久免费精品| 色婷婷综合久久久久| 亚洲欧洲第一视频| 91精品视频免费观看| 91色中文字幕| 欧美在线视频播放| 国产精品一区二区av影院萌芽| 亚洲成人av中文字幕| 国产一区二区免费| 亚洲精品免费一区二区三区| 国产精品久久一| 国产一区二区三区中文| 久久久成人的性感天堂| 91视频国产精品| 正在播放欧美视频| 日本一欧美一欧美一亚洲视频| xx视频.9999.com| 国产日韩欧美另类| 日韩少妇与小伙激情| 中文字幕在线成人| 精品视频在线播放色网色视频| 国产精品揄拍一区二区| 91国在线精品国内播放| 国产亚洲视频中文字幕视频| 91亚洲精品一区二区| 日韩有码在线观看| 亚洲国产女人aaa毛片在线| 亚洲精品一区二区在线| 91超碰中文字幕久久精品| 怡红院精品视频| 97婷婷大伊香蕉精品视频| 欧美午夜精品在线| 91手机视频在线观看| 亚洲最大成人在线| 日韩av免费看网站| 激情av一区二区| 国产日韩av在线播放| 性欧美暴力猛交69hd| 欧美日韩成人网| 国产91在线播放精品91| 国产婷婷成人久久av免费高清| 日韩经典一区二区三区| 91精品国产高清自在线| 亚洲一区中文字幕| 久久免费视频网站| 国产精品一二三在线| 欧美国产日韩中文字幕在线| 亚洲视频综合网| 久久亚洲精品一区二区| 精品亚洲精品福利线在观看| 欧美国产亚洲精品久久久8v| 久久视频精品在线| 日本三级韩国三级久久|