變數作用域是每門程式語言都會涉及的話題,也是身為程式設計師必需掌握的知識點,能深入掌握變數作用域更有助於你編寫穩定的程式。
一、JavaScript作用域分類
JavaScript就兩種作用域:全域(window)、函數級(function)。函數級(function)不要理解為「塊級(大括號{}級)」。
二、區分及定義JavaScript全域變數與局部變數
1.1定義在所有函數最外邊,使用或不使用var關鍵字定義的變數都是全域變數。全域變數其實被解析成window物件的屬性,所以我們可以以「window.全域變數名稱」方式存取它,建議在沒有必要的情況下直接使用變數名稱存取。如下範例示範了全域變數定義最常見的方法:
var msg1='This is message 1'; msg2='This is message 2'; alert(window.msg1); //This is message 1 使用window关键字进行访问 alert(window.msg2); //This is message 2 alert(msg1); //This is message 1 省略window关键字的访问方式 alert(msg2); //This is message 2 function otherFunction(){} //其它一些函数或对象声明代码 var otherObject={};
1.2在函數內(局部變數執行階段環境)一樣可以定義並取得全域變數。定義的方法就是不使用var關鍵字,在局部環境中亦可輕鬆取得全域變數內容,直接使用全域變數名稱引用即可。要注意的是:如果函數內定義了與全域變數同名的局部變量,那麼此時函數體將優先使用自己的局部變量,如果此時你非要使用同名的全域變量,請加上window前綴。舉例如下:
var msg1='This is message 1'; var msg3='This is message 3'; function otherFunction() { msg2='This is message 2'; //不使用var关键字,其实也是定义一个全局变量 var msg3='Message 3'; alert(msg1); //This is message 1 (函数内当然可以访问到外面定义的全局变量,再深的函数嵌套一样能正确获到这个全局变量,这是JavaScript闭包的其中一种体现) alert(msg3); //Message 3 (局部变量msg3) alert(window.msg3); //This is message 3 (使用window前缀访问同名的全局变量msg3) alert(this.msg3); //This is message 3 (因为otherFunction ()定义在一个全局的环境中,此时otherFunction ()的this也是指向window,所有你看到window. msg3是等于this. msg3的) } otherFunction(); //otherFunction函数外面定义的msg1和里面定义的msg2依然是全局变量 alert(window.msg1); //This is message 1 alert(window.msg2); //This is message 2
2.1使用var關鍵字,在函數體內定義的變數是局部變量,此變數能供其下面所有語句區塊({})及子函數使用。這個變數在這個函數裡任何地方都可以訪問到,但卻不能在這個函數的外面「直接」訪問(閉包允許間接訪問,或代理訪問,此知識點不在本文討論範圍)。舉例如下:
function showMsg() { if (true) { var msg='This is message'; } alert(msg); //This is message } showMsg(); alert(typeof(msg)); //undefiend //这里在if {}大括号内定义的变量msg还能在if外showMsg()内访问到,但在showMsg()外则是无法访问的
2.2父函數的變數可以被子函數訪問,但子函數的變數卻不能被父函數訪問,顯然這與我們一開始說的函數級作用域是相吻合的。這看起來老爸爽快些,兒子吝嗇些。舉例如下:
function showMsg() { var MsgA='Message A'; this.setMsg=function(msg) { var MsgB='Message B'; alert(MsgA); //Message A (子函数setMsg()可以访问父函数showMsg()的局部变量MsgA) } alert(MsgB); //MsgB未定义 (在父函数中不能访问其子函数中定义的变量MsgB) } var sm=new showMsg(); sm.setMsg('Message string');
三、使用技巧
1、為了避免變數混亂或被覆蓋,對於局部變數的定義一定不要忘記加上var關鍵字(必要時我們要變數使用完後主動釋放它,即「變數名稱=null」),同時建議把所有變數集中定義在每個函數體內的開頭位置。舉例如下:
var msg='Message'; function showMsg() { var msg; //这里即使不小心使用了与全局变量一样的变量名,也不用担心覆盖同名全局变量的问题 var a; var b; var c; for (a=0;a<10;a++){} this.setMsg=function(){} }
2、巧用匿名函數,減少命名衝突或變數污染。以下兩段程式碼其實實現了相同的功能,而第一段程式碼寫法自己可以在那個匿名函數內大膽用自己想用的變數名稱等,不用擔心自己定義的變數覆蓋其他人定義或自己其它地方定義的變數。
//定义一个匿名函数,然后把代码丢到这个匿名函数里面,能有效减少命名冲突或变量污染,这是常见JS框架的做法 (function() { var msg='This is message'; alert(msg); })(); document.write(msg); //msg未定义 (匿名函数外的其它方法已无法调用msg这个变量) //----------------------------- var msg='This is message'; alert(msg);
3、不建議在無須實例化的函數內使用this取代window去存取全域變數。一般情況使用this關鍵字的函數應作為JavaScript類別來處理(我喜歡把「cls」當作類別名稱的前綴)。以下函數如果只當作普通函數呼叫一下,就不應該出現this關鍵字,因為這通常是去操作一個全域變數了。例:
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();
以上是JavaScript變數作用域分類與使用技巧實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!