javascript
javascript基础拾遗——词法作用域
本來是想寫js面向?qū)ο蠊P記(二)關(guān)于封裝的,但是在敲實(shí)例代碼的時(shí)候,發(fā)現(xiàn)對(duì)作用域這個(gè)東西的概念有點(diǎn)模糊,翻閱了犀牛后,有點(diǎn)感覺了,就想著先記錄下此時(shí)的感受。
之所以取名叫做詞法作用域,是這個(gè)概念是js中相當(dāng)基礎(chǔ)也是極為重要的,很多想當(dāng)然的錯(cuò)誤或感覺怪異的問題都是和這個(gè)東西有關(guān)。所以,本文主要說下這個(gè)名詞的概念以及討論下他牽扯出來的有關(guān)變量、函數(shù)、閉包的問題。
1.由變量開始談
習(xí)慣性先來段代碼:
1 var x = "globol value";
2 var getValue = function(){
3 alert(x); //彈出"undefined"
4 var x = "local value";
5 alert(x); //彈出"local value";
6 }
7 getValue();
代碼很簡單,首先定義了一個(gè)全局變量x并賦了初值,然后寫了個(gè)getValue的方法,之后我們用alert彈出x的值,但是結(jié)果是undefined,不是global value也不是local value,這個(gè)我們可能會(huì)感覺到奇怪。其實(shí)理解這個(gè)問題的關(guān)鍵就是要清楚x的作用域。
第一個(gè)var x中的x是全局變量,說到這里順帶說下,js解釋器在執(zhí)行任何代碼之前會(huì)先創(chuàng)建一個(gè)全局對(duì)象(global object),全局變量就是相當(dāng)于這個(gè)全局對(duì)象的一個(gè)屬性。同理,對(duì)于getValue這個(gè)函數(shù),就會(huì)生成一個(gè)叫做調(diào)用對(duì)象的東西,局部變量就是這個(gè)調(diào)用對(duì)象的屬性,例子中第二個(gè)var x中的x就是局部變量。
2.主角登場(chǎng)
說了以上的東西其實(shí)是為了將本文的主角——詞法作用域。這個(gè)是何方神圣呢?要理解的話,其實(shí)我們可以對(duì)比傳統(tǒng)面向?qū)ο蟮?#xff08;如JAVA、C#)中的變量的作用域,我們知道C#中的變量作用域是塊級(jí)的,即這個(gè)變量只能活動(dòng)在定義他的一個(gè)直接外界內(nèi),如if子句內(nèi),for子句內(nèi)定義的變量外界是無法讀取的。而js中呢,變量卻不是這樣的,在同一個(gè)函數(shù)內(nèi)定義的變量其它的成員是可以訪問的。看個(gè)例子會(huì)清楚很多:
1 function test(o){
2 var i = 0;
3 if(typeof o == "object"){
4 var j = 0;
5 for(var k=0; k < 10; k++){
6 document.write(k);
7 }
8 document.write(k); //k是可以被訪問到的,即使他在for子句內(nèi)
9 }
10 document.write(j); //說明j是可以被訪問到的,即使他在if子句內(nèi)
11 }
清楚了這一點(diǎn)后,就來理解下js中關(guān)于詞法作用域的含義。當(dāng)定義了一個(gè)函數(shù)后,當(dāng)前的作用域就會(huì)被保存下來,并且成為函數(shù)內(nèi)部狀態(tài)的一部分,這個(gè)是很重要的一個(gè)概念。下面我們回到開篇的那個(gè)例子,當(dāng)getValue函數(shù)被定義的時(shí)候,他的作用域被保存起來,還有被加到作用域鏈上,他的上端就是全局執(zhí)行環(huán)境。當(dāng)調(diào)用getValue方法的時(shí)候,js解釋器首先會(huì)把作用域設(shè)置為定義函數(shù)的時(shí)候的那個(gè)作用域(即之前保存那個(gè)),接下來,他在作用域的前加上調(diào)用對(duì)象即getValue這個(gè)函數(shù),再在他的上端加上全局對(duì)象。暈了沒?還是看下我畫的圖把:
這樣比較清楚了把,這個(gè)作用域鏈其實(shí)和原型鏈有點(diǎn)相似,也好似在很作用域內(nèi)找不到就會(huì)向上去找。比方說開篇那個(gè)例子,找x的時(shí)候,(對(duì)了這里要先介紹下js的預(yù)定義機(jī)制,就是js解釋器會(huì)先對(duì)var定義的變量進(jìn)行初始化,應(yīng)該說只是起了定義的作用當(dāng)沒賦值),會(huì)先在本作用域內(nèi)找,有預(yù)定義知可以找到x,但是沒賦值,所以是undefined值。知道了這點(diǎn)我們來知道開篇那個(gè)代碼其實(shí)是等價(jià)于下面這個(gè)的:
1 var x = "globol value";
2 var getValue = function(){
3 var x;
4 alert(x); //彈出"undefined"
5 x = "local value";
6 alert(x); //彈出"local value";
7 }
8 getValue();
實(shí)際上js解釋器做的事情應(yīng)該是按以上這個(gè)例子執(zhí)行的,所以從另一個(gè)角度說,將變量的定義放在開頭這個(gè)約定是有意義并且有益處的。
3.延伸
清楚了以上關(guān)于詞法作用域的概念后,我們就不難理解閉包的概念了,他只是用到了作用域鏈的不可向下性(我取的名詞..),即下面的作用域可以訪問上面的,但上面的不可以訪問下面的。當(dāng)然這只是構(gòu)成閉包的一個(gè)條件,閉包更重要的還是外部函數(shù)持有內(nèi)部函數(shù)的一個(gè)嵌套函數(shù)的引用,由于閉包不是本文主要要討論的(ps:談封裝的時(shí)候會(huì)說到),所以只是簡單看下例子:
1 function foo(){
2 var age = 10;
3 function boo(){
4 age += 10;
5 return age;
6 }
7 return boo;
8 }
9
10 var tx = new foo();
11 alert(tx()); //20
4.總結(jié)
詞法作用域的討論就先這樣了,我想說得是這個(gè)概念還是相當(dāng)重要的。當(dāng)然本文的內(nèi)容也只是我針對(duì)書本介紹的自我的一些看法和理解,有不得當(dāng)?shù)牡胤较M魑恢赋?#xff0c;好了,回去睡覺了~
轉(zhuǎn)載于:https://www.cnblogs.com/Quains/archive/2011/04/12/2013121.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的javascript基础拾遗——词法作用域的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 类WebOS(添加了主界面,及相关功能代
- 下一篇: MD5数据加密于文件加密