JS進階之路之——作用域(一)

        我們常說,萬物都有其存在的價值,這話的確不錯,但是深思一下,是不是需要有個前提,萬物都在某些領域或多或少的存在某些價值。

        舉個例子,汽車,絕對是個非常有價值的stuff,它給我們的日常出行,貨物運輸等帶來了極大的便利;筷子,同樣也是個非常有價值的stuff,它給我們吃飯帶來了極大的方便。但是,汽車能幫我們把菜送到嘴裏嗎?筷子能載着我們出行嗎?

        那麼,我上面所說的某些領域,我們是不是可以稱其爲作用域,我想是可以的。

        說到這,那麼我就想問了:在JS裏,作用域是不是也是類似的概念呢?

首先,我可以肯定的說這是一個在JavaScript中灰常灰常重要的概念,關係着JS裏很多核心的機制,理解它,很多問題都迎刃而解了。

        那麼,問問自己,在JS裏,作用域是什麼?

        心裏大概知道是什麼,但是細細一想又好像說不太清。

        沒關係,下面我們就細細品味這個有意思的東東。

先throw概念吧:

        作用域負責收集並維護由所有聲明的標識符(變量)組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的代碼對這些標識符的訪問權限。

        通俗來說,作用域相當於一個管理員(有自己的一套規則),他負責管理所有聲明的標識符的有序查詢。

        我們來講個故事,說說作用域到底幹了啥。

三兄弟齊上陣

long long ago,有3個關係很好的基友,老大叫引擎,老二叫編輯器,老三叫作用域。三兄弟眼看年歲已長,可手上還是沒有幾個銀子。個個都很着急,於是三兄弟謀劃一同做個事。

求職過程:此粗略去數萬個字。。。

最終他們做的工作是:負責JS的編譯和運行。

他們的工作內容是這樣的:

老闆甩給他們一項任務編譯並執行下面代碼:

var a = 1;
console.log( a );

開始工作:

  • 編譯器:作用域,幫我看看你那有沒有儲存變量a。
  • 作用域:二哥,還沒有。

  • 編譯器:那好,幫我儲存一個。

  • 引擎: 老三,你那有沒有一個叫做a的變量。

  • 編譯器:大哥,還真有,剛二哥讓我存儲了一個。

  • 引擎: 真是太好了,幫我拿出來,它的值是幾,我需要給它複製。

  • 編譯器:大哥,它的值是2。

  • 引擎: 謝謝你,三弟,這樣我就能打印它的值了。

上面講了一個不恰當的小故事,但是三者之間的關係大概就是這樣。


詞法作用域 VS 動態作用域

        徹底搞懂JavaScript作用域裏介紹過,大部分標準語言編譯器的第一個工作階段叫作詞法化(也叫單詞化)。回憶一下,詞法化的過程會對源代碼中的字符進行檢查,如果是有狀態的解析過程,還會賦予單詞語義。

        在JS裏,使用的作用域就是詞法作用域。

簡單地說,詞法作用域就是定義在詞法階段的作用域。換句話說,詞法作用域是由你在寫代碼時將變量和塊作用域寫在哪裏來決定的,因此當詞法分析器處理代碼時會保持作用域不變(大部分情況下是這樣的)。

      

在JS裏,動態作用域和this機制息息相關。它的作用域詩是在運行的過程中確定的

var a = 1;
function fn() {    
    var a = 2;    
    console.log( this.a );
}
fn(); // 1

從上面的代碼,我們可以看出:fn中打印a的值不是由寫代碼的位置確定的,而是取決於fn執行的位置。

  • 區別

  • 詞法作用域是在寫代碼或者說定義時確定的,而動態作用域是在運行時確定的。(this 也是!)

  • 詞法作用域關注函數在何處聲明,而動態作用域關注函數從何處調用。

函數作用域

JS裏,生成作用域的方式:

  • 函數

  • with、eval (不建議使用,影響性能)

由此,我們知道JS裏,絕大多數的作用域都是基於函數生成的。

每個函數都會爲自身生成一個作用域氣泡。這個氣泡內所有的標識符都可以在這個氣泡中使用。

function bar() {    
    var a = 1;    
    function fn() {        
        var b = 2;        
        console.log(b);    
    }    
 fn();    
 console.log(a);
}
bar();

上面代碼,bar氣泡有標識符a、fn,因此在bar氣泡中可以訪問到a、fn; fn氣泡有標識符b,因此在bar氣泡中可以訪問到b; 當然還有一個全局氣泡,全局氣泡中有bar標識符,因此在全局氣泡中可以訪問到bar。





發佈了24 篇原創文章 · 獲贊 40 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章