理解JavaScript變量作用域更輕松
更新時(shí)間:2009年10月25日 11:41:47 作者:
變量作用域是每門編程語(yǔ)言都會(huì)涉及的話題,也是作為一名程序員必需掌握的知識(shí)點(diǎn),能深入掌握變量作用域更有助于你編寫穩(wěn)定的程序。
JavaScript本身作為一門簡(jiǎn)單的語(yǔ)言,就其變量作用域問(wèn)題一樣令不少人頭暈,這主要是因?yàn)镴avaScript閉包的存在。本文不打算深入講解JavaScript變量作用域問(wèn)題(其實(shí)本人也沒(méi)有能力能把這一話題講的深入些),也不講“閉包”話題,本文只討論最實(shí)用的JavaScript作用域知識(shí)點(diǎn)。
一、JavaScript作用域分類
JavaScript就兩種作用域:全局(window)、函數(shù)級(jí)(function)。函數(shù)級(jí)(function)不要理解為“塊級(jí)(大括號(hào){}級(jí))”。
二、區(qū)分及定義JavaScript全局變量與局部變量
1.1定義在所有函數(shù)最外邊,使用或不使用var關(guān)鍵字定義的變量都是全局變量。全局變量其實(shí)被解析成window對(duì)象的一個(gè)屬性,所以我們可以以“window.全局變量名”方式訪問(wèn)它,推薦在沒(méi)有必要的情況下直接使用變量名訪問(wèn)。如下例子演示了全局變量定義最常見(jiàn)的方法:
var msg1='This is message 1';
msg2='This is message 2';
alert(window.msg1); //This is message 1 使用window關(guān)鍵字進(jìn)行訪問(wèn)
alert(window.msg2); //This is message 2
alert(msg1); //This is message 1 省略window關(guān)鍵字的訪問(wèn)方式
alert(msg2); //This is message 2
function otherFunction(){} //其它一些函數(shù)或?qū)ο舐暶鞔a
var otherObject={};
1.2在函數(shù)內(nèi)(局部變量運(yùn)行時(shí)環(huán)境)一樣可以定義和獲取全局變量。定義的方法就是不使用var關(guān)鍵字,而在局部環(huán)境中亦可輕松獲得全局變量?jī)?nèi)容,直接使用全局變量名引用即可。需要注意的是:如果函數(shù)內(nèi)定義了與全局變量同名的局部變量,那么此時(shí)函數(shù)體將優(yōu)先使用自己的局部變量,如果此時(shí)你非要使用同名的全局變量,請(qǐng)加上window前綴。舉例如下:
var msg1='This is message 1';
var msg3='This is message 3';
function otherFunction()
{
msg2='This is message 2'; //不使用var關(guān)鍵字,其實(shí)也是定義一個(gè)全局變量
var msg3='Message 3';
alert(msg1); //This is message 1 (函數(shù)內(nèi)當(dāng)然可以訪問(wèn)到外面定義的全局變量,再深的函數(shù)嵌套一樣能正確獲到這個(gè)全局變量,這是JavaScript閉包的其中一種體現(xiàn))
alert(msg3); //Message 3 (局部變量msg3)
alert(window.msg3); //This is message 3 (使用window前綴訪問(wèn)同名的全局變量msg3)
alert(this.msg3); //This is message 3 (因?yàn)閛therFunction ()定義在一個(gè)全局的環(huán)境中,此時(shí)otherFunction ()的this也是指向window,所有你看到window. msg3是等于this. msg3的)
}
otherFunction();
//otherFunction函數(shù)外面定義的msg1和里面定義的msg2依然是全局變量
alert(window.msg1); //This is message 1
alert(window.msg2); //This is message 2
2.1使用var關(guān)鍵字,在函數(shù)體內(nèi)定義的變量是局部變量,此變量能供其下面所有語(yǔ)句塊({})及子函數(shù)使用。這個(gè)變量在這個(gè)函數(shù)里任何地方都可以訪問(wèn)到,但卻不能在這個(gè)函數(shù)的外面“直接”訪問(wèn)(閉包允許間接訪問(wèn),或代理訪問(wèn),此知識(shí)點(diǎn)不在本文討論范圍)。舉例如下:
function showMsg()
{
if (true)
{
var msg='This is message';
}
alert(msg); //This is message
}
showMsg();
alert(typeof(msg)); //undefiend
//這里在if {}大括號(hào)內(nèi)定義的變量msg還能在if外showMsg()內(nèi)訪問(wèn)到,但在showMsg()外則是無(wú)法訪問(wèn)的
2.2父函數(shù)的變量可以被子函數(shù)訪問(wèn),但子函數(shù)的變量卻不能被父函數(shù)訪問(wèn),顯然這與我們一開(kāi)始說(shuō)的函數(shù)級(jí)作用域是相吻合的。這看起來(lái)老爸爽快些,兒子吝嗇些。舉例如下:
function showMsg()
{
var MsgA='Message A';
this.setMsg=function(msg)
{
var MsgB='Message B';
alert(MsgA); //Message A (子函數(shù)setMsg()可以訪問(wèn)父函數(shù)showMsg()的局部變量MsgA)
}
alert(MsgB); //MsgB未定義 (在父函數(shù)中不能訪問(wèn)其子函數(shù)中定義的變量MsgB)
}
var sm=new showMsg();
sm.setMsg('Message string');
三、需要注意的幾個(gè)地方及使用技巧
1、為了避免變量混亂或被覆蓋,對(duì)于局部變量的定義一定不要忘記加上var關(guān)鍵字(必要時(shí)我們要變量使用完后主動(dòng)釋放它,即“變量名=null”),同時(shí)建議把所有變量集中定義在每個(gè)函數(shù)體內(nèi)的開(kāi)頭位置。舉例如下:
var msg='Message';
function showMsg()
{
var msg; //這里即使不小心使用了與全局變量一樣的變量名,也不用擔(dān)心覆蓋同名全局變量的問(wèn)題
var a;
var b;
var c;
for (a=0;a<10;a++){}
this.setMsg=function(){}
}
2、巧用匿名函數(shù),減少命名沖突或變量污染。如下兩段代碼其實(shí)實(shí)現(xiàn)了相同的功能,而第一段代碼寫法自己可以在那個(gè)匿名函數(shù)內(nèi)大膽用自己想用的變量名等,不用擔(dān)心自己定義的變量覆蓋其他人定義或自己其它地方定義的變量。
//定義一個(gè)匿名函數(shù),然后把代碼丟到這個(gè)匿名函數(shù)里面,能有效減少命名沖突或變量污染,這是常見(jiàn)JS框架的做法
(function()
{
var msg='This is message';
alert(msg);
})();
document.write(msg); //msg未定義 (匿名函數(shù)外的其它方法已無(wú)法調(diào)用msg這個(gè)變量)
//-----------------------------
var msg='This is message';
alert(msg);
3、不建議在無(wú)須實(shí)例化的函數(shù)內(nèi)使用this代替window去訪問(wèn)全局變量。一般情況使用this關(guān)鍵字的函數(shù)應(yīng)當(dāng)作為JavaScript類來(lái)處理(我喜歡把“cls”作為類名的前綴)。以下函數(shù)如果僅當(dāng)作普通函數(shù)調(diào)用一下,就不應(yīng)該出現(xiàn)this關(guān)鍵字,因?yàn)檫@通常是去操作一個(gè)全局變量了。例子:
function clsMsg()
{
this.msg='This is default message';
this.showMsg=function()
{
alert(this.msg);
}
}
sMsg=new clsMsg();
sMsg.msg='This is new message';
sMsg.showMsg();
四、相關(guān)知識(shí)點(diǎn)指引
理解以下相關(guān)知識(shí)點(diǎn)有助于你更好地認(rèn)識(shí)JavaScript變量作用域,本文暫不詳述,隨后會(huì)以單獨(dú)篇幅來(lái)講,敬請(qǐng)關(guān)注。
(1)理解JavaScript“預(yù)解析”
(2)JavaScript閉包
一、JavaScript作用域分類
JavaScript就兩種作用域:全局(window)、函數(shù)級(jí)(function)。函數(shù)級(jí)(function)不要理解為“塊級(jí)(大括號(hào){}級(jí))”。
二、區(qū)分及定義JavaScript全局變量與局部變量
1.1定義在所有函數(shù)最外邊,使用或不使用var關(guān)鍵字定義的變量都是全局變量。全局變量其實(shí)被解析成window對(duì)象的一個(gè)屬性,所以我們可以以“window.全局變量名”方式訪問(wèn)它,推薦在沒(méi)有必要的情況下直接使用變量名訪問(wèn)。如下例子演示了全局變量定義最常見(jiàn)的方法:
復(fù)制代碼 代碼如下:
var msg1='This is message 1';
msg2='This is message 2';
alert(window.msg1); //This is message 1 使用window關(guān)鍵字進(jìn)行訪問(wèn)
alert(window.msg2); //This is message 2
alert(msg1); //This is message 1 省略window關(guān)鍵字的訪問(wèn)方式
alert(msg2); //This is message 2
function otherFunction(){} //其它一些函數(shù)或?qū)ο舐暶鞔a
var otherObject={};
1.2在函數(shù)內(nèi)(局部變量運(yùn)行時(shí)環(huán)境)一樣可以定義和獲取全局變量。定義的方法就是不使用var關(guān)鍵字,而在局部環(huán)境中亦可輕松獲得全局變量?jī)?nèi)容,直接使用全局變量名引用即可。需要注意的是:如果函數(shù)內(nèi)定義了與全局變量同名的局部變量,那么此時(shí)函數(shù)體將優(yōu)先使用自己的局部變量,如果此時(shí)你非要使用同名的全局變量,請(qǐng)加上window前綴。舉例如下:
復(fù)制代碼 代碼如下:
var msg1='This is message 1';
var msg3='This is message 3';
function otherFunction()
{
msg2='This is message 2'; //不使用var關(guān)鍵字,其實(shí)也是定義一個(gè)全局變量
var msg3='Message 3';
alert(msg1); //This is message 1 (函數(shù)內(nèi)當(dāng)然可以訪問(wèn)到外面定義的全局變量,再深的函數(shù)嵌套一樣能正確獲到這個(gè)全局變量,這是JavaScript閉包的其中一種體現(xiàn))
alert(msg3); //Message 3 (局部變量msg3)
alert(window.msg3); //This is message 3 (使用window前綴訪問(wèn)同名的全局變量msg3)
alert(this.msg3); //This is message 3 (因?yàn)閛therFunction ()定義在一個(gè)全局的環(huán)境中,此時(shí)otherFunction ()的this也是指向window,所有你看到window. msg3是等于this. msg3的)
}
otherFunction();
//otherFunction函數(shù)外面定義的msg1和里面定義的msg2依然是全局變量
alert(window.msg1); //This is message 1
alert(window.msg2); //This is message 2
2.1使用var關(guān)鍵字,在函數(shù)體內(nèi)定義的變量是局部變量,此變量能供其下面所有語(yǔ)句塊({})及子函數(shù)使用。這個(gè)變量在這個(gè)函數(shù)里任何地方都可以訪問(wèn)到,但卻不能在這個(gè)函數(shù)的外面“直接”訪問(wèn)(閉包允許間接訪問(wèn),或代理訪問(wèn),此知識(shí)點(diǎn)不在本文討論范圍)。舉例如下:
復(fù)制代碼 代碼如下:
function showMsg()
{
if (true)
{
var msg='This is message';
}
alert(msg); //This is message
}
showMsg();
alert(typeof(msg)); //undefiend
//這里在if {}大括號(hào)內(nèi)定義的變量msg還能在if外showMsg()內(nèi)訪問(wèn)到,但在showMsg()外則是無(wú)法訪問(wèn)的
2.2父函數(shù)的變量可以被子函數(shù)訪問(wèn),但子函數(shù)的變量卻不能被父函數(shù)訪問(wèn),顯然這與我們一開(kāi)始說(shuō)的函數(shù)級(jí)作用域是相吻合的。這看起來(lái)老爸爽快些,兒子吝嗇些。舉例如下:
復(fù)制代碼 代碼如下:
function showMsg()
{
var MsgA='Message A';
this.setMsg=function(msg)
{
var MsgB='Message B';
alert(MsgA); //Message A (子函數(shù)setMsg()可以訪問(wèn)父函數(shù)showMsg()的局部變量MsgA)
}
alert(MsgB); //MsgB未定義 (在父函數(shù)中不能訪問(wèn)其子函數(shù)中定義的變量MsgB)
}
var sm=new showMsg();
sm.setMsg('Message string');
三、需要注意的幾個(gè)地方及使用技巧
1、為了避免變量混亂或被覆蓋,對(duì)于局部變量的定義一定不要忘記加上var關(guān)鍵字(必要時(shí)我們要變量使用完后主動(dòng)釋放它,即“變量名=null”),同時(shí)建議把所有變量集中定義在每個(gè)函數(shù)體內(nèi)的開(kāi)頭位置。舉例如下:
復(fù)制代碼 代碼如下:
var msg='Message';
function showMsg()
{
var msg; //這里即使不小心使用了與全局變量一樣的變量名,也不用擔(dān)心覆蓋同名全局變量的問(wèn)題
var a;
var b;
var c;
for (a=0;a<10;a++){}
this.setMsg=function(){}
}
2、巧用匿名函數(shù),減少命名沖突或變量污染。如下兩段代碼其實(shí)實(shí)現(xiàn)了相同的功能,而第一段代碼寫法自己可以在那個(gè)匿名函數(shù)內(nèi)大膽用自己想用的變量名等,不用擔(dān)心自己定義的變量覆蓋其他人定義或自己其它地方定義的變量。
復(fù)制代碼 代碼如下:
//定義一個(gè)匿名函數(shù),然后把代碼丟到這個(gè)匿名函數(shù)里面,能有效減少命名沖突或變量污染,這是常見(jiàn)JS框架的做法
(function()
{
var msg='This is message';
alert(msg);
})();
document.write(msg); //msg未定義 (匿名函數(shù)外的其它方法已無(wú)法調(diào)用msg這個(gè)變量)
//-----------------------------
var msg='This is message';
alert(msg);
3、不建議在無(wú)須實(shí)例化的函數(shù)內(nèi)使用this代替window去訪問(wèn)全局變量。一般情況使用this關(guān)鍵字的函數(shù)應(yīng)當(dāng)作為JavaScript類來(lái)處理(我喜歡把“cls”作為類名的前綴)。以下函數(shù)如果僅當(dāng)作普通函數(shù)調(diào)用一下,就不應(yīng)該出現(xiàn)this關(guān)鍵字,因?yàn)檫@通常是去操作一個(gè)全局變量了。例子:
復(fù)制代碼 代碼如下:
function clsMsg()
{
this.msg='This is default message';
this.showMsg=function()
{
alert(this.msg);
}
}
sMsg=new clsMsg();
sMsg.msg='This is new message';
sMsg.showMsg();
四、相關(guān)知識(shí)點(diǎn)指引
理解以下相關(guān)知識(shí)點(diǎn)有助于你更好地認(rèn)識(shí)JavaScript變量作用域,本文暫不詳述,隨后會(huì)以單獨(dú)篇幅來(lái)講,敬請(qǐng)關(guān)注。
(1)理解JavaScript“預(yù)解析”
(2)JavaScript閉包
您可能感興趣的文章:
- JavaScript的變量作用域深入理解
- 關(guān)于javascript 回調(diào)函數(shù)中變量作用域的討論
- 關(guān)于JavaScript中var聲明變量作用域的推斷
- Javascript變量作用域詳解
- JavaScript 變量作用域及閉包
- javascript權(quán)威指南 學(xué)習(xí)筆記之變量作用域分享
- javascript變量作用域使用中常見(jiàn)錯(cuò)誤總結(jié)
- 深入解析JavaScript中的變量作用域
- javascript 的變量、作用域和內(nèi)存問(wèn)題
- 簡(jiǎn)單談?wù)刯avascript中的變量、作用域和內(nèi)存問(wèn)題
- JavaScript變量作用域及內(nèi)存問(wèn)題實(shí)例分析
相關(guān)文章
JavaScript架構(gòu)前端監(jiān)控搭建過(guò)程步驟
這篇文章主要為大家介紹了JavaScript架構(gòu)前端監(jiān)控搭建過(guò)程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06js前端實(shí)現(xiàn)登錄拼圖驗(yàn)證功能
行為驗(yàn)證碼通過(guò)用戶的操作來(lái)完成驗(yàn)證,常見(jiàn)的行為驗(yàn)證碼有拖動(dòng)式和點(diǎn)觸式,下面這篇文章主要給大家介紹了關(guān)于js前端實(shí)現(xiàn)登錄拼圖驗(yàn)證功能的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02一些經(jīng)常會(huì)用到的Javascript檢測(cè)函數(shù)
一些經(jīng)常會(huì)用到的Javascript檢測(cè)函數(shù),都是在prototype上面的擴(kuò)展。2010-05-05微信小程序通過(guò)點(diǎn)擊事件跨頁(yè)面?zhèn)鲄⒓癲ata-方法傳參(data-)的示例詳解
在?vue?中,我們可以直接在點(diǎn)擊事件中放入傳遞的參數(shù)進(jìn)行傳參;然而微信小程序中并不適用這樣的寫法,但是微信小程序可以通過(guò)自定義屬性從而綁定參數(shù)使用,這篇文章主要介紹了微信小程序通過(guò)點(diǎn)擊事件跨頁(yè)面?zhèn)鲄⒁约癲ata-方法傳參(data-),需要的朋友可以參考下2023-12-12JavaScript獲取網(wǎng)頁(yè)表單提交方式的方法
這篇文章主要介紹了JavaScript獲取網(wǎng)頁(yè)表單提交方式的方法,可判斷表單提交方式是get還是post,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04JS時(shí)間戳與日期格式互相轉(zhuǎn)換的簡(jiǎn)單方法示例
這篇文章主要給大家介紹了關(guān)于JS時(shí)間戳與日期格式互相轉(zhuǎn)換的簡(jiǎn)單方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11js實(shí)現(xiàn)時(shí)鐘定時(shí)器
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)時(shí)鐘定時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03