JavaScript作用域--總結

       JavaScript作用域是什麼?咋一問讓人確實很懵逼。

       作用域這個詞耳熟能詳,但作用域是什麼,經常用卻不知怎麼說起。

       先從定義上來說,我覺得《不知道的JavaScript》一書說得很清晰,作用域是一套查找變量的規則。查找又從何說起?又是怎麼一個查找法?

       說起這個不得不說JavaScript的運行過程,在我們看來,瀏覽器就是加載JavaScript然後執行,簡單的來講就是這樣,但實際過程中,JavaScript是加載完成之後先編譯再去運行的,說到這個是不是有種熟悉的感覺,vue模板也是同樣的原理,將模板編譯成JavaScript代碼。編譯過程經歷了三個階段,分別是分詞/詞法分析、解析/語法分析、代碼生成。

       分詞/詞法分析,這個階段就是將輸入的字符串分割成有意義的代碼塊(詞法單元),比如說,"var a = 1;" 會將該字符串分割成 "var"、"a"、"="、"1"、";",至於爲什麼這麼分割完全取決於字符是否有意義,換句話說,只要你的編譯器支持,"全局變量 a 等於 1 ;" ===  "var a = 1;"都行,總的來講就是一種符號規則,即使換成漢字也是一樣。

        解析/語法分析,這個階段是將上一階段的詞法單元通過一套規則整合起來,整合的結果稱之爲抽象語法樹(Abstract Syntax Tree,AST)。AST是爲接下來的代碼生成做準備,既然都叫樹了,所以是個嵌套式的,那問題來了,就一定是要嵌套的嗎?我個人倒覺得取決於代碼生成的規則,主流的還是嵌套式的。

       代碼生成,這個階段生成可執行的代碼。

       那麼問題來了這個和作用域啥關係?JavaScript作用域其實應該叫做詞法作用域,這裏規定了一套變量查找規則,還是那個例子,"var a = 1;",以"="爲界,左側的爲左側查找,右側爲右側查找,左側查找會查找的是是否聲明,在es6中,let,const 不允許重複聲明,重複聲明的話會報錯,var聲明在同級作用域重複則直接被捨棄,右側如果是變量的話也會查找,至於查找規則則是層層向上查找,作用域是嵌套式的,形象一點的將就像對象一樣,鍵值對層層嵌套,就是也就是樹數據結構的形式。

       作用域嵌套有點類似數學中集合的概率,全局作用域就像總集合,局部作用域A就相當於總集合的一個子集合,其實這裏有個比較有意思的問題,爲啥查找只能向上查找,我試着搜索過這個問題,未能找到相關的資料,個人猜測,這個可能和語言設計有關,比如封裝,如果上層作用域能使用下層作用域變量的話,那就不存在封裝這一回事了,也就是都是全局變量,命名也是個大麻煩。

       從類型上來講,作用域分爲全局作用域、函數作用域、塊級作用域。

       全局作用域顧名是在最外層,貫穿了整個程序運行之內,在程序中任何一個位置都能去方位全局作用域中的變量。

       函數作用域,其實也是和局部作用域效果相似,可以訪問上層作用域中的變量,上層作用域無法訪問下層函數作用域內的變量。說到這個不得不說一下局部作用域,es6有自己的模塊規範,一個文件可以生成一個模塊,每個模塊也可以相當於一個局部變量。

       塊級作用域,也是es6裏面的,let,const 申明能在花括號裏面形成類似局部作用域效果,花括號外無法方位花括號內let、const申明的變量。

       作用域裏面還有一個動態作用域的概念,而JavaScript是非動態作用域。

        寫到這其實也就差不多,不過關於作用域怎麼下定義,就是一件有趣的事了,emmm,抄一下維基百科的定義:

電腦程序設計中,作用域(scope,或譯作有效範圍)是名字(name)與實體(entity)的綁定(binding)保持有效的那部分計算機程序。不同的編程語言可能有不同的作用域名字解析。而同一語言內也可能存在多種作用域,隨實體類型變化而不同。作用域類別影響變量綁定方式,根據語言使用靜態作用域還是動態作用域變量的取值可能會有不同的結果。

名字空間是一種作用域,使用作用域的封裝性質去邏輯上組羣起關相的衆識別子於單一識別子之下。因此,作用域可以影響這些內容的名字解析

程序員常會縮進他們的源代碼中的作用域,改善可讀性。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章