【Q2】變量名與函數(shù)名重名問(wèn)題俊抵,你是否傻傻分不清呢?

有時(shí)做題時(shí)坐梯,不難發(fā)現(xiàn)有些題目在實(shí)際開(kāi)發(fā)工作中可能并不會(huì)如此書(shū)寫(xiě)代碼徽诲,但,它能考察你對(duì)基礎(chǔ)知識(shí)的掌握程度吵血。就好比本文要說(shuō)的變量名與函數(shù)名重復(fù)的情況谎替。講解前先看題,如下:



這道題結(jié)果輸出是多少呢践瓷?有小伙伴可能會(huì)說(shuō)輸出10院喜,也有小伙伴可能會(huì)覺(jué)得是輸出20,那么晕翠,究竟是多少呢喷舀?又是為什么呢?在講解答案前淋肾,我們先做點(diǎn)知識(shí)點(diǎn)儲(chǔ)備工作:

  • 變量聲明提升

在執(zhí)行函數(shù)test時(shí)硫麻,函數(shù)作用域內(nèi)有非聲明變量x = 20;語(yǔ)句,有些小伙伴可能會(huì)認(rèn)為在執(zhí)行完函數(shù)test后樊卓,函數(shù)內(nèi)部非聲明變量x被隱式地創(chuàng)建為全局變量拿愧,且正好覆蓋已在全局顯示聲明的變量x的值,因此認(rèn)為結(jié)果輸出是20碌尔。這很大可能是認(rèn)為輸出為20的小伙伴們的解答浇辜。

在這里我們需要清楚聲明變量非聲明變量的差異中的兩點(diǎn):

1.聲明變量的作用域限制在其聲明位置的上下文中,而非聲明變量總是全局的唾戚。
2.聲明變量在任何代碼執(zhí)行前創(chuàng)建柳洋,而非聲明變量只有在執(zhí)行賦值操作時(shí)才會(huì)被創(chuàng)建。

不是很清楚上述兩點(diǎn)的小伙伴可以參考JavaScript語(yǔ)句和聲明之var叹坦,里面有很詳細(xì)的講解栗子熊镣。

  • 函數(shù)聲明提升

還有部分小伙伴,可能會(huì)認(rèn)為JavaScript引擎是由上而下執(zhí)行代碼募书,當(dāng)執(zhí)行函數(shù)test時(shí)绪囱,執(zhí)行到第4行函數(shù)內(nèi)部return;語(yǔ)句使得終止函數(shù)體內(nèi)代碼執(zhí)行跳出函數(shù)體莹捡,覺(jué)得函數(shù)x沒(méi)任何作用鬼吵。其實(shí),我們要知道的是篮赢,函數(shù)聲明也是會(huì)被提升的而柑,也就是說(shuō)函數(shù)x的聲明會(huì)被提升到其對(duì)應(yīng)作用域的最頂層文捶。

不懂變量提升函數(shù)提升的小伙伴可以參看JavaScript:變量提升和函數(shù)提升

簡(jiǎn)單來(lái)說(shuō)媒咳,就是JS引擎在解析JavaScript代碼之前會(huì)先將代碼進(jìn)行預(yù)編譯粹排,預(yù)編譯期間會(huì)將所有的變量聲明和函數(shù)聲明提升到其對(duì)應(yīng)的作用域的最頂層。且會(huì)先執(zhí)行變量聲明提升涩澡,再執(zhí)行函數(shù)聲明提升顽耳,也就是函數(shù)聲明提升優(yōu)先級(jí)比變量聲明提升優(yōu)先級(jí)高,要注意這個(gè)優(yōu)先級(jí)高是說(shuō)函數(shù)聲明提升要晚妙同,后執(zhí)行射富。關(guān)于變量聲明提升和函數(shù)聲明提升優(yōu)先級(jí)問(wèn)題,在本文最后再作討論驗(yàn)證粥帚。

有了以上知識(shí)點(diǎn)儲(chǔ)備胰耗,可以隱式地將題目代碼理解為:

var x;   //變量x聲明提升
function test(){  //函數(shù)test聲明提升
  function x() {  //函數(shù)x聲明提升
    console.log(x);
  }
  x = 20;
  return;
}
x = 10;
test();
console.log(x);

有了上述預(yù)解析后代碼,小伙伴們是否覺(jué)得答案呼之欲出呢芒涡?如果仍然覺(jué)得結(jié)果輸出為20柴灯,則大家忽略了文章關(guān)鍵點(diǎn):變量名與函數(shù)名重名!

不過(guò)费尽,在這之前大家還需要理解作用域鏈的知識(shí)點(diǎn)赠群,這里就簡(jiǎn)單介紹下:

  • 作用域鏈?zhǔn)嵌鄠€(gè)上下級(jí)關(guān)系的作用域形成的鏈, 它的方向是從下向上的(從內(nèi)到外)
  • 查找變量時(shí),就是沿著作用域鏈來(lái)查找的

簡(jiǎn)單地說(shuō)旱幼,就是嵌套的作用域產(chǎn)生的有內(nèi)向外(由下向上)的作用域鏈查描,用于查找變量的。

那么柏卤,理解作用域鏈的小伙伴知道冬三,在查找一個(gè)變量時(shí),沿著作用域鏈由內(nèi)向外查找缘缚,如果在當(dāng)前作用域查找到對(duì)應(yīng)變量长豁,就直接返回,否則就往其上一級(jí)作用域進(jìn)行查找忙灼;如果在上一級(jí)作用域內(nèi)查找到就直接返回,否則就繼續(xù)向上一級(jí)作用域查找钝侠;直到全局作用域该园,如果還未找到就拋出ReferenceError異常。

接著帅韧,我們繼續(xù)分析上述預(yù)解析后代碼:
1.首先里初,聲明變量x,系統(tǒng)在棧內(nèi)存中為變量x分配內(nèi)存空間忽舟,初始化賦值為undefined双妨;
2.再聲明函數(shù)test淮阐,系統(tǒng)在棧內(nèi)存中為函數(shù)名test分配內(nèi)存空間,值為堆內(nèi)存中創(chuàng)建的函數(shù)對(duì)象的內(nèi)存地址值刁品;
3.執(zhí)行賦值語(yǔ)句x = 10泣特,將變量x賦值為10;
4.執(zhí)行函數(shù)test挑随,函數(shù)test內(nèi)部也有函數(shù)聲明且函數(shù)名為x状您,緊接著函數(shù)x定義下有同名變量x賦值語(yǔ)句x = 20;,這時(shí)就需要用到前面講的作用域鏈知識(shí)點(diǎn):
????1).在執(zhí)行函數(shù)test時(shí)兜挨,函數(shù)體內(nèi)部并未調(diào)用執(zhí)行函數(shù)函數(shù)x膏孟,故函數(shù)x內(nèi)的代碼并不會(huì)被執(zhí)行;
????2).執(zhí)行函數(shù)test內(nèi)x = 20;時(shí)拌汇,按著作用域鏈由內(nèi)向外查找變量x柒桑,先在當(dāng)前函數(shù)test作用域內(nèi)查找,當(dāng)前函數(shù)作用域內(nèi)已聲明同名函數(shù)x的函數(shù)對(duì)象(重名T胍ā)魁淳,因此找到同名函數(shù)x后,就不再查找傅联;
????3).賦值語(yǔ)句x = 20;實(shí)際上是給函數(shù)名為x的函數(shù)對(duì)象重新賦值為20先改。
5.經(jīng)過(guò)前面分析可知,賦值語(yǔ)句x = 20;是給函數(shù)test作用域內(nèi)的函數(shù)對(duì)象x賦值為20蒸走,所以最后在全局作用域內(nèi)執(zhí)行console.log(x);仇奶,訪問(wèn)的是全局變量x,且全局變量x值為10比驻,故此最終輸出結(jié)果為10该溯。

到此為止,小伙伴們應(yīng)該清楚為什么這道題輸出結(jié)果是10别惦,而不是20的整個(gè)分析過(guò)程了哈狈茉!

為了驗(yàn)證大家是否有真正明白其中涉及到的知識(shí)點(diǎn),下面將題目稍作改動(dòng)如下掸掸,輸出結(jié)果又是多少呢氯庆?

var x = 10;  
function test(){  
  x = 20;
  return;
}
test();
console.log(x);

相信大家有了上述分析的基礎(chǔ),題目答案一目了然為20呢扰付!那么堤撵,為什么呢?簡(jiǎn)單解析下就是在執(zhí)行函數(shù)test內(nèi)x = 20;時(shí)羽莺,沿著作用域鏈由內(nèi)向外查找變量x实昨,在當(dāng)前函數(shù)作用域內(nèi)未找到變量x,則會(huì)向上一級(jí)作用域查找盐固,而上一級(jí)作用域就是全局作用域荒给,在全局作用域內(nèi)找到已聲明的變量x丈挟,故給全局變量x賦值為20。
接著志电,再次將代碼作改動(dòng)如下:

function test(){  
  x = 20;
  return;
}
test();
console.log(x);

那么曙咽,這個(gè)輸出結(jié)果又是多少呢?相信大家會(huì)不約而同地回答20溪北。對(duì)桐绒,沒(méi)錯(cuò),就是20之拨。為啥呢茉继?很簡(jiǎn)單,在函數(shù)test內(nèi)部有未聲明變量x進(jìn)行賦值操作后蚀乔,會(huì)被隱式地創(chuàng)建為全局變量烁竭,所以在全局作用域內(nèi)執(zhí)行console.log(x);,輸出結(jié)果毫無(wú)疑問(wèn)當(dāng)然就是20呢吉挣!

至此派撕,這道重名問(wèn)題的題也算卸下帷幕呢!接下來(lái)睬魂,就文章前面提到的變量聲明提升和函數(shù)聲明提升優(yōu)先級(jí)問(wèn)題來(lái)驗(yàn)證下终吼。

function bar() {}
var bar;
console.log(bar,typeof bar);   //? bar() {} "function"
var bar;
function bar() {}
console.log(bar,typeof bar);  //? bar() {} "function"

運(yùn)行結(jié)果均為? bar() {} "function",這也就驗(yàn)證了前面說(shuō)到的函數(shù)聲明提升優(yōu)先級(jí)比變量聲明提升優(yōu)先級(jí)高氯哮,而且际跪,再次強(qiáng)調(diào)下,需要注意喉钢,這個(gè)優(yōu)先級(jí)高是說(shuō)函數(shù)聲明提升要晚姆打,后執(zhí)行!3λ洹幔戏!好多人會(huì)誤理解為優(yōu)先級(jí)高就是先執(zhí)行,導(dǎo)致網(wǎng)上好多解釋都是云里霧里的税课。

那么闲延,今天的分享就到這里啦!如果發(fā)現(xiàn)文章內(nèi)容有誤韩玩,歡迎評(píng)論指出錯(cuò)誤垒玲,感謝ing!

如果你覺(jué)得這篇文章對(duì)你有幫助啸如,請(qǐng)點(diǎn)贊支持一下哦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載氮惯,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者叮雳。
  • 序言:七十年代末想暗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子帘不,更是在濱河造成了極大的恐慌说莫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寞焙,死亡現(xiàn)場(chǎng)離奇詭異储狭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)捣郊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)辽狈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人呛牲,你說(shuō)我怎么就攤上這事刮萌。” “怎么了娘扩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵着茸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我琐旁,道長(zhǎng)涮阔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任灰殴,我火速辦了婚禮敬特,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘验懊。我一直安慰自己擅羞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布义图。 她就那樣靜靜地躺著减俏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碱工。 梳的紋絲不亂的頭發(fā)上娃承,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音怕篷,去河邊找鬼历筝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛廊谓,可吹牛的內(nèi)容都是我干的梳猪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蒸痹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼春弥!你這毒婦竟也來(lái)了呛哟?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤匿沛,失蹤者是張志新(化名)和其女友劉穎扫责,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體逃呼,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳖孤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抡笼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苏揣。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蔫缸,靈堂內(nèi)的尸體忽然破棺而出腿准,到底是詐尸還是另有隱情,我是刑警寧澤拾碌,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布吐葱,位于F島的核電站,受9級(jí)特大地震影響校翔,放射性物質(zhì)發(fā)生泄漏弟跑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一防症、第九天 我趴在偏房一處隱蔽的房頂上張望孟辑。 院中可真熱鬧,春花似錦蔫敲、人聲如沸饲嗽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)貌虾。三九已至,卻和暖如春裙犹,著一層夾襖步出監(jiān)牢的瞬間尽狠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工叶圃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袄膏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓掺冠,卻偏偏與公主長(zhǎng)得像沉馆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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