跟我學(xué)習(xí)javascript的全局變量
一、盡量少用全局對(duì)象
全局變量的問(wèn)題在于,你的JavaScript應(yīng)用程序和web頁(yè)面上的所有代碼都共享了這些全局變量,他們住在同一個(gè)全局命名空間,所以當(dāng)程序的兩個(gè)不同部分定義同名但不同作用的全局變量的時(shí)候,命名沖突在所難免。
web頁(yè)面包含不是該頁(yè)面開(kāi)發(fā)者所寫的代碼也是比較常見(jiàn)的,例如:
- 第三方的JavaScript庫(kù)
- 廣告方的腳本代碼
- 第三方用戶跟蹤和分析腳本代碼
- 不同類型的小組件,標(biāo)志和按鈕
比方說(shuō),該第三方腳本定義了一個(gè)全局變量,叫做result;接著,在你的函數(shù)中也定義一個(gè)名為result的全局變量。其結(jié)果就是后面的變量覆蓋前面的,第三方腳本就一下子嗝屁啦!
因?yàn)?,你不小心,在代碼的某一處修改了全局變量, 會(huì)導(dǎo)致依賴全局變量的其它模塊出錯(cuò)。而且出錯(cuò)原因難調(diào)試,難找到。
再者就是,網(wǎng)頁(yè)運(yùn)行肯定用到window對(duì)象,瀏覽器引擎又要遍歷一次window的屬性,性能下降。
- 全局變量是維系不同模塊之間的紐帶,模塊之間只能通過(guò)全局變量來(lái)訪問(wèn)對(duì)方提供的功能
- 能使用局部變量的時(shí)候,絕不要使用全局變量
var i,n,sum//globals function averageScore(players){ sum =0; for(i = 1, i = player.length; i<n; i++){ sum += score(players[i]); } return sum/n; }
保持這些變量為局部變量,僅將其作為需要使用它們的代碼的一部分。
function averageScore(players){ var i,n,sum; sum =0; for(i = 1, i = player.length; i<n; i++){ sum += score(players[i]); } return sum/n; }
在browser中,this關(guān)鍵字會(huì)指向全局的window對(duì)象
JavaScript 的全局命名空間也被暴露為在程序全局作用域中可以訪問(wèn)的全局對(duì)象,該對(duì)象作為 this 關(guān)鍵字的初始值。在 Web 瀏覽器中,全局對(duì)象被綁定到全局的 window 變量。添加或修改全局變量會(huì)自動(dòng)更新全局對(duì)象。
this.foo; //undefined foo ="global foo"; //"global foo" this.foo; //"global foo"
類似地,更新全局對(duì)象也會(huì)自動(dòng)地更新全局命名空間:
var foo ="global foo"; this.foo; //"global foo" this.foo ="changed"; foo; //"changed"
兩種用來(lái)改變?nèi)謱?duì)象的方式,通過(guò)var關(guān)鍵字聲明以及給全局對(duì)象設(shè)置屬性(通過(guò)this關(guān)鍵字)
通過(guò)全局對(duì)象進(jìn)行針對(duì)當(dāng)前運(yùn)行環(huán)境的特性檢測(cè)(Feature Detection),比如在ES5中提供了一個(gè)JSON對(duì)象用來(lái)操作JSON數(shù)據(jù),那么可以通過(guò)if(this.JSON)來(lái)判斷當(dāng)前運(yùn)行環(huán)境是否支持JSON
if(!this.JSON){ this.JSON ={ parse:..., stringify:... } }
二、如何避免全局變量
方法一:只創(chuàng)建一個(gè)全局變量。
MYAPP.stooge = { "first-name": "Joe", "last-name": "Howard" }; MYAPP.flight = { airline: "Oceanic", number: 815, departure: { IATA: "SYD", time: "2004-09-22 14:55", city: "Sydney" }, arrival: { IATA: "LAX", time: "2004-09-23 10:42", city: "Los Angeles" } };
方法二:使用模塊模式
var serial_maker = function ( ) { // Produce an object that produces unique strings. A // unique string is made up of two parts: a prefix // and a sequence number. The object comes with // methods for setting the prefix and sequence // number, and a gensym method that produces unique // strings. var prefix = ''; var seq = 0; return { set_prefix: function (p) { prefix = String(p); }, set_seq: function (s) { seq = s; }, gensym: function ( ) { var result = prefix + seq; seq += 1; return result; } }; }( ); var seqer = serial_maker( ); seqer.set_prefix = 'Q'; seqer.set_seq = 1000; var unique = seqer.gensym( ); // unique is "Q1000"
所謂模塊模式,就是創(chuàng)建一個(gè)函數(shù),該函數(shù)包括,私有變量和一個(gè)特權(quán)對(duì)象,特權(quán)對(duì)象的內(nèi)容是,利用閉包能訪問(wèn)到私有變量的函數(shù),最后返回特權(quán)對(duì)象。
首先,方法二,不僅可以當(dāng)作全局變量用,也可以用在局部聲明全局變量。因?yàn)榫退隳阍诓恢滥硞€(gè)地方修改了seqer,就會(huì)立即報(bào)錯(cuò),因?yàn)檫@是個(gè)對(duì)象,不是字符串。
方法三:零全局變量
零全局變量實(shí)際上是為了適應(yīng)一小段封閉代碼而采取的一種局部變量處理方式,只適合在一些特殊場(chǎng)景中使用。最常見(jiàn)的就是一些不會(huì)被其他腳本訪問(wèn)到的完全獨(dú)立的腳本。
使用零全局變量的方式需要采用立即執(zhí)行函數(shù),用法如下。
( function ( win ) { 'use strict' ; var doc = win.document ; //在此定義其他的變量并書(shū)寫代碼 } )
三、意外的全局變量
由于JavaScript的兩個(gè)特征,不自覺(jué)地創(chuàng)建出全局變量是出乎意料的容易。首先,你可以甚至不需要聲明就可以使用變量;第二,JavaScript有隱含的全局概念,意味著你不聲明的任何變量都會(huì)成為一個(gè)全局對(duì)象屬性。參考下面的代碼:
function sum(x, y) { // 不推薦寫法: 隱式全局變量 result = x + y; return result; }
此段代碼中的result沒(méi)有聲明。代碼照樣運(yùn)作正常,但在調(diào)用函數(shù)后你最后的結(jié)果就多一個(gè)全局命名空間,這可以是一個(gè)問(wèn)題的根源。
經(jīng)驗(yàn)法則是始終使用var聲明變量,正如改進(jìn)版的sum()函數(shù)所演示的:
function sum(x, y) { var result = x + y; return result; }
另一個(gè)創(chuàng)建隱式全局變量的反例就是使用任務(wù)鏈進(jìn)行部分var聲明。下面的片段中,a是本地變量但是b確實(shí)全局變量,這可能不是你希望發(fā)生的:
// 反例,勿使用 function foo() { var a = b = 0; // ... }
此現(xiàn)象發(fā)生的原因在于這個(gè)從右到左的賦值,首先,是賦值表達(dá)式b = 0,此情況下b是未聲明的。這個(gè)表達(dá)式的返回值是0,然后這個(gè)0就分配給了通過(guò)var定義的這個(gè)局部變量a。換句話說(shuō),就好比你輸入了:
var a = (b = 0);
如果你已經(jīng)準(zhǔn)備好聲明變量,使用鏈分配是比較好的做法,不會(huì)產(chǎn)生任何意料之外的全局變量,如:
function foo() { var a, b; // ... a = b = 0; // 兩個(gè)均局部變量 }
然而,另外一個(gè)避免全局變量的原因是可移植性。如果你想你的代碼在不同的環(huán)境下(主機(jī)下)運(yùn)行,使用全局變量如履薄冰,因?yàn)槟銜?huì)無(wú)意中覆蓋你最初環(huán)境下不存在的主機(jī)對(duì)象
總是記得通過(guò)var關(guān)鍵字來(lái)聲明局部變量
使用lint工具來(lái)確保沒(méi)有隱式聲明的全局變量
以上就是對(duì)javascript的全局變量介紹,希望對(duì)大家的學(xué)習(xí)有所幫助。
- javascript 用局部變量來(lái)代替全局變量
- javascript(jquery)利用函數(shù)修改全局變量的代碼
- JavaScript中全局變量、函數(shù)內(nèi)變量以及常量表達(dá)式的效率測(cè)試
- javascript中運(yùn)用閉包和自執(zhí)行函數(shù)解決大量的全局變量問(wèn)題
- javascript全局變量封裝模塊實(shí)現(xiàn)代碼
- 基于JavaScript 聲明全局變量的三種方式詳解
- 探討JavaScript中聲明全局變量三種方式的異同
- Javascript全局變量var與不var的區(qū)別深入解析
- javascript中局部變量和全局變量的區(qū)別詳解
相關(guān)文章
JavaScript實(shí)現(xiàn)消息對(duì)話框
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)消息對(duì)話框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09bootstrap日期插件daterangepicker使用詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap日期插件daterangepicker的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10手把手教你用Javascript實(shí)現(xiàn)觀察者模式
這篇文章主要為大家介紹了Javascript觀察者模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12js中位數(shù)不足自動(dòng)補(bǔ)位擴(kuò)展padLeft、padRight實(shí)現(xiàn)代碼
這篇文章主要介紹了js中位數(shù)不足自動(dòng)補(bǔ)位擴(kuò)展之padLeft、padRight實(shí)現(xiàn)方法,主要是通過(guò)String.prototype擴(kuò)展實(shí)現(xiàn),需要的朋友可以參考下2020-04-04JavaScript中使用參數(shù)個(gè)數(shù)實(shí)現(xiàn)重載功能
這篇文章主要介紹了JavaScript中使用參數(shù)個(gè)數(shù)實(shí)現(xiàn)重載功能,需要的朋友可以參考下2017-09-09JavaScript 開(kāi)發(fā)中規(guī)范性的一點(diǎn)感想
在開(kāi)發(fā)中通用的幾個(gè)方法,我們把它們放到utility目錄下或者utility.js中;所有的提示信息和報(bào)錯(cuò)信息統(tǒng)一放置在一起??雌饋?lái)都是小小的幾步,卻能讓咱們開(kāi)發(fā)的代碼同事讀起來(lái)更順暢,下個(gè)項(xiàng)目中也能用上。2009-06-06