javascript復(fù)習(xí)筆記(1)

  • 目的

    最近完成了一個(gè)項(xiàng)目和即將要進(jìn)入一個(gè)新的項(xiàng)目聪铺,在這段時(shí)間內(nèi)相對(duì)來說,可以靜下來看看書萄窜,索性重頭過一遍js铃剔。故記錄在簡(jiǎn)書,如果我的文字有問題查刻,請(qǐng)各位評(píng)論區(qū)評(píng)論键兜。

  • 正文

一、 var a = 2 時(shí)穗泵,發(fā)生了什么普气?
var a = 2;

這句代碼,任何一個(gè)寫過js的同學(xué)肯定會(huì)寫過這行聲明和賦值語句佃延。但是當(dāng)我們寫下這句話時(shí)现诀,js是如何解析的
首先履肃,這整個(gè)過程需要編譯器仔沿,引擎作用域三者來合作尺棋。編譯器會(huì)先去詢問作用域是否存在變量a, 如果是已經(jīng)聲明過的于未,那么 var a就會(huì)被忽略,如果不存在呢陡鹃,就會(huì)創(chuàng)建一個(gè)名為a的變量烘浦。然后編譯器繼續(xù)編譯代碼給引擎運(yùn)行。引擎運(yùn)行時(shí)萍鲸,會(huì)去查詢變量a闷叉,如果找到了,就會(huì)進(jìn)行賦值操作脊阴,將2賦值給a握侧。反之,則一直往上面的作用域找嘿期,一直找到全局的作用域品擎,如果這個(gè)時(shí)候還找不到,就拋出一個(gè)ReferenceError的錯(cuò)誤备徐。
其中引擎的查詢方式有兩種萄传,LHSRHS。前者意味查詢變量是否存在蜜猾,一般是為了賦值秀菱,后者是查詢值振诬,即查詢值的來源,一般用于獲取值衍菱。舉個(gè)例子:

function b (a) {
  console.log(a);
}
b(1) // 1

這里呢赶么,首先第四行是一個(gè)RHS查詢,因?yàn)橐鎴?zhí)行到這里時(shí)脊串,它會(huì)去查詢b這個(gè)變量辫呻,獲取b, 然后執(zhí)行b這個(gè)函數(shù)。然后第二行的為了將a的值傳進(jìn)給console.log也是會(huì)進(jìn)行一次RHS查詢琼锋。而調(diào)用函數(shù)b時(shí)傳入一個(gè)1的參數(shù)印屁,這個(gè)1賦值給a這個(gè)形參時(shí),會(huì)發(fā)生一個(gè)LHS查詢斩例。

二、作用域

前面有提到了作用域从橘,js有兩種作用域念赶,一個(gè)是全局作用域,一個(gè)是函數(shù)作用域恰力。

(function () {
   var a = 2;
   console.log(a);
   if (true) {
     var a = 1;
     console.log(a);
   }
     console.log(a);
})();

按照C++這類有塊級(jí)作用域的語言叉谜,這里是會(huì)輸出2,1踩萎,2停局,但是js的話,結(jié)果只會(huì)是2香府,1董栽,1。這說明了js這種寫法是不存在塊級(jí)作用域的企孩。如果使用let的話锭碳,就可以達(dá)到塊級(jí)作用域的效果。而作用域之間的關(guān)系勿璃,函數(shù)級(jí)作用域被包含在全局作用域中擒抛,而函數(shù)級(jí)作用域可以包含別的函數(shù)級(jí)作用域。如下圖的代碼:

var a = 1;
function outer () {
  var a = 2;
  function inner () {
  console.log(a);
  }
  inner();
}
outer();

全局作用域中有變量a和函數(shù)outer, 函數(shù)outer的作用域中變量a和函數(shù)inner, 而函數(shù)inner也有一個(gè)作用域补疑。所以說這里是三層作用域的嵌套歧沪。之前也說了,當(dāng)我們?cè)谧饔糜蛑幸樵円粋€(gè)變量或函數(shù)時(shí)莲组,引擎會(huì)進(jìn)行查詢诊胞,而查詢的方式就是從當(dāng)前的作用域,一直向上面的作用域?qū)ふ仪妈荆钡饺肿饔糜蛳峋绻也坏骄蜁?huì)發(fā)出一個(gè)錯(cuò)誤鳞尔,告訴你該引用不存在。而作用域具有隱蔽性早直。意思是寥假,子作用域可以訪問父作用域,而父作用域是不可能訪問得到子作用域霞扬。

var a = 1;
function outer () {
  var a = 2;
  function inner () {
    console.log(a);
  }
    inner();
}
inner(); // throw Error : inner is not defined

總之記住糕韧,在當(dāng)前作用域使用一個(gè)變量或者調(diào)用一個(gè)函數(shù)時(shí),只會(huì)從當(dāng)前作用域出發(fā)喻圃,去查詢萤彩,當(dāng)前查不到,就會(huì)往父作用域查詢斧拍,不會(huì)往子作用域查詢的雀扶,一直查詢到全局作用域,最后還查不到就說明沒有聲明肆汹∮弈梗可以思考下,下面的代碼輸出什么昂勉?

var a = 1;
function outer () {
  var a = 2;
  inner();
}
function inner () {
  console.log(a);
}
outer(); 

另外要注意的兩點(diǎn):

  • 在當(dāng)前作用域內(nèi)(非全局作用域)聲明一個(gè)變量時(shí)浪册,一定得用var, let 或者 const
    a = 1;
    
    這樣的代碼是不會(huì)報(bào)錯(cuò)的,因?yàn)樗鼤?huì)在隱式在全局聲明一個(gè)變量a(非
    嚴(yán)格模式下)岗照,這不是添亂么村象。。所以要避免攒至。
  • 當(dāng)js越寫越多代碼時(shí)厚者,很容易會(huì)造成作用域污染。比如在你不經(jīng)意間聲明了一個(gè)變量迫吐,它與你若干天前聲明的一個(gè)變量的名字一毛一樣籍救,而且在同一個(gè)作用域下運(yùn)作,比如全局作用域渠抹,那往往會(huì)給你和你的合作者帶來很多麻煩蝙昙,因?yàn)檫@根本不會(huì)報(bào)錯(cuò)好吧。js只會(huì)忽略你的這個(gè)新的 聲明語句梧却,然后給那個(gè)已經(jīng)存在的變量賦值奇颠。這就很難debug了。所以呢放航,要謹(jǐn)慎使用js的作用域烈拒。后面我會(huì)出一篇文章說下這方面的解決方法。
三、提升

大家來看下下面的代碼荆几,如果你是強(qiáng)類型語言的愛好者吓妆,我覺得會(huì)給你帶來很大的疑惑,答案相信大家熟悉提升之后吨铸,就會(huì)知道了行拢。

(() => {
  console.log(a);
  a();
  var a = 1;
  console.log(a);
  function a () {
    console.log(2);
  }
  a();
})()

js里有一種很不一樣的機(jī)制就是提升機(jī)制了。其中有兩種東西可以提升诞吱。一個(gè)是變量聲明提升和函數(shù)聲明提升舟奠。以下面的例子講解變量聲明提升:

(() => {
  console.log(a); // undefined
  if (true) {
    var a = 2;
  }
  console.log(a); // 2
})()

按道理來說,強(qiáng)類型語言的代碼是有順序的房维,沒有執(zhí)行到 var a = 2; 時(shí)沼瘫,變量a應(yīng)該未聲明的,但是這里卻輸出了undefined咙俩。其實(shí)耿戚,這就是js的變量聲明的提升了,上面的代碼阿趁,其實(shí)執(zhí)行順序是這樣的:

(() => {
  var a;
  console.log(a); // undefined
  if (true) {
    a = 2;
  }
  console.log(a); // 2
})()

變量a的聲明被提升到最開始的位置膜蛔,而賦值語句則被留在了原地。而函數(shù)聲明也類似:

(() => {
  fun(); // 1
  function fun () {
    console.log(1);
  }
})()

函數(shù)fun會(huì)被執(zhí)行歌焦,這是因?yàn)楹瘮?shù)聲明被提前到fun()之前了。但是注意砚哆,函數(shù)表達(dá)式是不具備提升的独撇,即下面的代碼是不會(huì)正常運(yùn)行的。

(() => {
  fun(); // fun is not a function
  var fun =  () => {
    console.log(1);
  }
})()

上面的代碼可以理解為躁锁,對(duì)fun的聲明被提到最前纷铣,但那個(gè)時(shí)候fun還是undefined,所以當(dāng)成函數(shù)來調(diào)用就會(huì)拋出了錯(cuò)誤战转。

那么問題又來了搜立,當(dāng)一個(gè)函數(shù)內(nèi),同時(shí)具有變量和函數(shù)槐秧,那么這兩者的提升是誰更優(yōu)先呢啄踊?答案是,函數(shù)的提升比變量的提升更優(yōu)先刁标,不信颠通?可以試試下面的代碼:

(() => {
  console.log(a);
  function a () {
    console.log(1);
  }
  var a = 1; 
})()

因此,個(gè)人建議膀懈,在一個(gè)函數(shù)內(nèi)在最開始的地方把需要用到的變量都聲明好顿锰,那就可以盡量避免提升帶來不必要的麻煩。

結(jié)語

這次先到這,如果有錯(cuò)請(qǐng)?jiān)u論吧硼控。寫這類文刘陶,一是讓自己去總結(jié)知識(shí),一方面是交流知識(shí)牢撼。有時(shí)候措辭不當(dāng)或者理解有誤匙隔,出了錯(cuò)誤,在所難免浪默,望大家監(jiān)督和寬容牡直。
(忘了說,最近看的書是 《你不知道的JavaScript》)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纳决,一起剝皮案震驚了整個(gè)濱河市碰逸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌阔加,老刑警劉巖饵史,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異胜榔,居然都是意外死亡胳喷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門夭织,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吭露,“玉大人,你說我怎么就攤上這事尊惰〗哺停” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵弄屡,是天一觀的道長题禀。 經(jīng)常有香客問我,道長膀捷,這世上最難降的妖魔是什么迈嘹? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮全庸,結(jié)果婚禮上秀仲,老公的妹妹穿的比我還像新娘。我一直安慰自己壶笼,他們只是感情好啄育,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拌消,像睡著了一般挑豌。 火紅的嫁衣襯著肌膚如雪安券。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天氓英,我揣著相機(jī)與錄音侯勉,去河邊找鬼。 笑死铝阐,一個(gè)胖子當(dāng)著我的面吹牛址貌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播徘键,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼练对,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了吹害?” 一聲冷哼從身側(cè)響起螟凭,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎它呀,沒想到半個(gè)月后螺男,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纵穿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年下隧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谓媒。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淆院,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出句惯,到底是詐尸還是另有隱情土辩,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布宗弯,位于F島的核電站脯燃,受9級(jí)特大地震影響搂妻,放射性物質(zhì)發(fā)生泄漏蒙保。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一欲主、第九天 我趴在偏房一處隱蔽的房頂上張望邓厕。 院中可真熱鬧,春花似錦扁瓢、人聲如沸详恼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昧互。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敞掘,已是汗流浹背叽掘。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玖雁,地道東北人更扁。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像赫冬,于是被迫代替她去往敵國和親浓镜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

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