JS作用域和重復(fù)聲明var背后的原理

JS的容錯(cuò)率很高慢洋,一些其他語言常見的小錯(cuò)誤JS都能大度得包容吹泡,比如給一個(gè)方法傳入超出預(yù)計(jì)的參數(shù)盟庞、在聲明變量之前使用該變量(變量的聲明提升解決了這個(gè)問題)等等阶剑,這里我們就要解剖一下JS變量重復(fù)聲明以及當(dāng)我們忽略var使用 a=2來聲明變量時(shí)a為全局變量的問題:

 //第一段代碼  
var a = 2;  
var a = 3;  
alert(a);//3  
//第二段代碼  
<span style="font-size:18px;"></span><pre name="code" class="javascript">a = 2;  
alert(a);//2  

這兩段代碼在JS的眼中是完全可行的跃巡,JS會(huì)默默忽略掉第二個(gè)var聲明來將程序繼續(xù)執(zhí)行下去,而且后面聲明的值會(huì)覆蓋掉前面聲明的值牧愁,而第二段代碼JS會(huì)將忽略var的聲明默認(rèn)聲明為全局變量素邪。這些大家都應(yīng)該很清楚,但是JS遇到重復(fù)聲明時(shí)背后到底是怎樣運(yùn)行的呢猪半?那就關(guān)系到了JS的幕后黑手:引擎以及他的左膀右臂:編譯器以及作用域兔朦。

在JS代碼運(yùn)行過程中:

引擎負(fù)責(zé)整個(gè)代碼的編譯以及運(yùn)行,編譯器則負(fù)責(zé)詞法分析磨确、語法分析沽甥、代碼生成等工作而作用域則如我們熟知的一樣,負(fù)責(zé)維護(hù)所有的標(biāo)識(shí)符(變量)乏奥。

當(dāng)我們執(zhí)行上面的代碼時(shí)摆舟,我們可以簡單的理解為新變量分配一塊兒內(nèi)存,命名為a,并賦值為2恨诱,但在運(yùn)行的時(shí)候編譯器與引擎還會(huì)進(jìn)行兩項(xiàng)額外的操作:判斷變量是否已經(jīng)聲明:

  1. 首先編譯器對(duì)代碼進(jìn)行分析拆解媳瞪,從左至右遇見var a,則編譯器會(huì)詢問作用域是否已經(jīng)存在叫a的變量了胡野,如果不存在材失,則招呼作用域聲明一個(gè)新的變量a,若已經(jīng)存在硫豆,則忽略var 繼續(xù)向下編譯龙巨,這時(shí)a = 2被編譯成可執(zhí)行的代碼供引擎使用。

  2. 引擎遇見a=2時(shí)同樣會(huì)詢問在當(dāng)前的作用域下是否有變量a熊响,若存在旨别,則將a賦值為2(由于第一步編譯器忽略了重復(fù)聲明的var,且作用域中已經(jīng)有a汗茄,所以重復(fù)聲明會(huì)發(fā)生值得覆蓋而并不會(huì)報(bào)錯(cuò))秸弛。若不存在,則順著作用域鏈向上查找洪碳,若最終找到了變量a則將其賦值2递览,若沒有找到,則招呼作用域聲明一個(gè)變量a并賦值為2(這就是為什么第二段代碼可以正確執(zhí)行且a變量為全局變量的原因瞳腌,當(dāng)然绞铃,在嚴(yán)格模式下JS會(huì)直接拋出異常:a is not defined)。

雖然JS很勤勞嫂侍,可以幫我們解決一些小問題儿捧,但是作為程序員的我們最好按照代碼規(guī)范來進(jìn)行書寫,于人于己都大有裨益挑宠,何樂而不為呢菲盾。

注:關(guān)于a = 2 a會(huì)被聲明為全局變量其中涉及到LHS查詢方式

在書寫代碼的時(shí)候我們無時(shí)無刻不在與作用域較勁,而引擎是如何在沿著作用域鏈把我們想要的東西查找出來的呢各淀?這里就涉及到了L與R的區(qū)別懒鉴。

通過字面意思就很容易理解L代表left R代表right,而LHS與RHS查詢我們可以先簡單的區(qū)分為:查詢在 = 號(hào)左邊的變量時(shí)碎浇,引擎使用LHS疗我,查詢在 = 右邊的變量時(shí),引擎使用RHS南捂。LHS查詢出來的是變量的地址吴裤,方便進(jìn)行形如a = 2的賦值操作,因?yàn)橐娓静恍枰P(guān)心a里面存的是什么鬼溺健,按照程序猿的要求把2塞給a就可以了麦牺,而RHS查詢出來的是變量存儲(chǔ)的值钮蛛,以便形如 a = b的賦值操作,引擎同樣不需要關(guān)心 b 放在內(nèi)存的哪個(gè)“格子”剖膳,只需要知道格子里面放的什么就可以了魏颓。

當(dāng)然, 根據(jù) = 左右來區(qū)分LHS RHS是不全面的吱晒,因?yàn)槲覀兒苋菀茁┑粢恍╇[藏的LHS與RHS:

 var c =3;  
 function a(b){  
 console.log(b+c);  
 }  
 a(2);  

在上面一段代碼中甸饱,我們可以很明顯的得出 c ...使用了LHS,console.log()中的b仑濒、c使用了RHS叹话,但是在調(diào)用函數(shù)a、console.log的時(shí)候同樣使用了RHS墩瞳,參數(shù)b的賦值也同樣使用了LHS,所以我們最好通過取值驼壶、取地址這兩個(gè)行為來判斷引擎使用的查詢方式。

對(duì)于上面的代碼喉酌,引擎與作用域是這樣交流的:

引擎:全局作用域热凹,我想找一下c,你見過他么泪电?
全局作用域:嗨般妙,別提了,編譯器那小子剛剛聲明了它相速,拿去吧股冗!
引擎:太棒了!我現(xiàn)在要把3丟給他
引擎:等一下和蚪,還有一個(gè)事情想麻煩你一下,我想對(duì)a函數(shù)進(jìn)行引用烹棉,你知道她在哪里么攒霹?
全局作用域:就是那個(gè)跟c一起被丟進(jìn)來的家伙把?喏浆洗,在這里呢催束,給你。
引擎:哈哈伏社,太感謝了抠刺,這樣我只需要把2.....。
a函數(shù)作用域:薩瓦迪卡摘昌,引擎速妖,今天天氣不錯(cuò)啊,一起出去玩吧聪黎!
引擎:別提了罕容,我手頭上忙的要死,對(duì)了,你碰到過一個(gè)叫b的么锦秒?
a函數(shù)作用域:哦露泊,他是a函數(shù)的一個(gè)形參,我這剛好有旅择,拿去用
引擎:夠哥們惭笑,這樣我只需要把2放到b里面,之后.....哎生真,小a,console你有么
a函數(shù)作用域:有有有沉噩,這是個(gè)內(nèi)置對(duì)象,給你
引擎:哈哈汇歹,你一直這么靠譜屁擅,我找找,哎呦产弹,真有l(wèi)og這個(gè)函數(shù)派歌,我得趕緊引用他
引擎:你看我這腦子,你能在幫我找一下b么痰哨,我得確認(rèn)一下b的內(nèi)容
a函數(shù)作用域:放心胶果,看!b沒有變過斤斧,放心
引擎:那最好了早抠,就差最后一步了,做完喝酒去撬讽,你那里有沒有c蕊连,交出來我請(qǐng)你一包辣條!
a函數(shù)作用域:真的么游昼!我找找甘苍,嗯.....不行,我這里沒有烘豌,你得去問問我大哥 全局作用域
引擎:全局作用域载庭,不好意思,又來找你了廊佩,不知道你有沒有c囚聚,我拿辣條跟你換
全局作用域:看你累的滿頭大汗的,辣條你自己留著吧标锄,c給你顽铸,做完快歇歇吧
引擎:么么噠,你最好了料皇,晚上我請(qǐng)你吃飯跋破!

看完上面的對(duì)話簸淀,不知道你對(duì)LHS RHS是否有了足夠的了解,還有一點(diǎn)需要注意的就是毒返,當(dāng)查找到全局作用域時(shí)租幕,若還沒有查找到要找的變量信息,若為LHS查詢拧簸,會(huì)默認(rèn)聲明一個(gè)與請(qǐng)求的變量同名的全局變量劲绪,而RHS則會(huì)拋出錯(cuò)誤,當(dāng)然盆赤,在嚴(yán)格模式下贾富,LHS也同樣會(huì)報(bào)錯(cuò),這是需要注意的地方牺六。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颤枪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淑际,更是在濱河造成了極大的恐慌畏纲,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件春缕,死亡現(xiàn)場離奇詭異盗胀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锄贼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門票灰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宅荤,你說我怎么就攤上這事屑迂。” “怎么了冯键?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵惹盼,是天一觀的道長。 經(jīng)常有香客問我琼了,道長,這世上最難降的妖魔是什么夫晌? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任雕薪,我火速辦了婚禮,結(jié)果婚禮上晓淀,老公的妹妹穿的比我還像新娘所袁。我一直安慰自己,他們只是感情好凶掰,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布燥爷。 她就那樣靜靜地躺著蜈亩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪前翎。 梳的紋絲不亂的頭發(fā)上稚配,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音港华,去河邊找鬼道川。 笑死,一個(gè)胖子當(dāng)著我的面吹牛立宜,可吹牛的內(nèi)容都是我干的冒萄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼橙数,長吁一口氣:“原來是場噩夢啊……” “哼尊流!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起灯帮,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤崖技,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后施流,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體响疚,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年瞪醋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忿晕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡银受,死狀恐怖践盼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宾巍,我是刑警寧澤咕幻,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站顶霞,受9級(jí)特大地震影響肄程,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜选浑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一蓝厌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧古徒,春花似錦拓提、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寺惫。三九已至,卻和暖如春蹦疑,著一層夾襖步出監(jiān)牢的瞬間西雀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工必尼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蒋搜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓判莉,卻偏偏與公主長得像豆挽,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子券盅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容