關(guān)于《你不知道的javascript》
編譯原理
關(guān)于編程語言蒲稳,我們會(huì)想到的一個(gè)基本知識(shí)點(diǎn)是:首先它可以存儲(chǔ)變量辑鲤,其次它能夠?qū)@個(gè)變量進(jìn)行訪問與修改捂刺。對(duì)于javascript递胧,實(shí)現(xiàn)這些功能多于其編譯器霎烙、引擎與作用域有關(guān)撬讽。那么我們今天就先從編譯器簡(jiǎn)單說起吧蕊连。
對(duì)于一般的編譯語言,編譯過程多在編碼前期執(zhí)行游昼,通過分詞==語法分析==代碼生成來將代碼編譯成機(jī)器指令甘苍。而對(duì)于js來說,編譯的過程也是比較復(fù)雜的烘豌,其中還涉及到很多的優(yōu)化項(xiàng)目载庭,但是一般來說,它沒有那么多的編譯時(shí)間廊佩,只會(huì)在執(zhí)行前對(duì)作用域中的代碼進(jìn)行編譯囚聚。
工作機(jī)制
以var a=2舉個(gè)例子吧,介紹一下編譯器與引擎和作用域怎樣工作的
- 首先标锄,編譯器看到了var a顽铸,向作用域來問a是否聲明過,是料皇,則無視谓松,繼續(xù)生成后面的代碼,否践剂,向作用域中添加a這個(gè)變量鬼譬。后續(xù)以代碼生成方式,生成a=2這個(gè)代碼逊脯,但沒有什么實(shí)際意義优质。
- 引擎開始工作,對(duì)于a=2的賦值語句军洼,先向作用域查找a變量巩螃,確認(rèn)a存在,將2賦值于a歉眷,如果這里不存在牺六,則會(huì)舉爪報(bào)錯(cuò)颤枪。
這里我們可以看到編譯器與引擎都會(huì)與作用域有相應(yīng)的交集汗捡,但是因?yàn)榫庉嬈髦恍枰袛嗍欠裥杪暶饕约白饔糜蚵暶靼蛇@樣的作用,好像體現(xiàn)不了作用域的重要性畏纲,作者就不說他兩之間的事了扇住,轉(zhuǎn)向一個(gè)更重要的地方,引擎如何在作用域中查找變量盗胀,以及確認(rèn)其是在哪一層--好像確實(shí)重要些艘蹋,其實(shí)就是不好理解嘛,就找了兩個(gè)方法來幫助我們?nèi)ダ斫庖幌逻@樣的查找機(jī)制票灰。
那些賦值左右的事情
我們看到的表達(dá)式女阀,其實(shí)大多只有兩種宅荤,一種是直接有‘=’的賦值語句,一種是純粹的函數(shù)執(zhí)行:console.log(‘就醬’)浸策。
- 那么對(duì)于賦值語句a=b來說冯键,對(duì)于a的查詢,我們可以知道庸汗,它只需要將告訴引擎==‘我就在這惫确,我的值你添加就好啦’,但是對(duì)于b蚯舱,我們需要先找到有沒有b改化,即是否聲明過,沒有聲明枉昏,抱歉陈肛,你出現(xiàn)了ReferenceError錯(cuò)誤啦。同樣兄裂,如果是console.log(b)燥爷,也是先查找到源頭,看是否聲明懦窘。
- 這里可以看出我們大致可以將在作用域中的查找變成兩種思路:LHS查詢和RHS查詢前翎,可以記憶為賦值左右的小竅門--為什么這么叫就不造啦。左邊的是LHS畅涂,a=港华。。午衰。立宜,我們只需要知道a存在,能找到它-即賦值的目標(biāo)臊岸。右邊的RHS橙数,a=b中的b可以理解為賦值的源頭,要確定它是否被聲明帅戒,是否有值灯帮。
RHS與LHS的意義何在
- 兩種查詢思路,更方面我們知道變量在作用域中是如何被查找到的
- 區(qū)別:非嚴(yán)格模式下逻住,a=2沒有聲明a一點(diǎn)毛病沒有钟哥,但是a=b,b沒有聲明就引用錯(cuò)誤啦瞎访;而且如果var b,a腻贰;a.b這種的b也是不行噠,會(huì)說類型錯(cuò)誤==TypeError
- 然后就是對(duì)于多層嵌套的作用域扒秸,我們可以很清楚的用這兩種方式去找變量啦播演,不著急冀瓦。
作用域是什么
說了半天,那么作用域到底是什么写烤,書里那一句話還不錯(cuò):作用域就是一種方法咕幻,用于確定在何處以及如何查找變量。
小羅嗦
寫文好慢的速度顶霞,那就隨便說說啦肄程,書中的觀點(diǎn)自己的話,有問題大家評(píng)論呀选浑,一起討論討論