javascript的語法作用域你真的懂了嗎


     有段時間沒有更新了,思緒一下子有點轉不過來。正應了一句古話“一天不讀書,無人看得出;一周不讀書,開始會爆粗;一月不讀書,智商輸給豬。”。再加上周五晚上看了下很久沒看的湖南綜藝節目《天天向上》關於出版書及讀書的相關內容,看到相當多的嘉賓家里的書房讓我驚嘆也伴隨着一種文人的向往。我雖然小的時候不太愛看書,但是隨着自己一點點的長大,也不知道什么時候開始也有買書藏書看書的情節,而且正如郁鈞劍老師所說的藏書有點會上癮,即使有些書不是馬上就會看。挺希望以后不工作了,有自己的一間書屋,一方書桌,一把椅子,一壺茶水,悠然自得的讀書練習書法。

話題有點跑題了,切換模式回到這篇博客上來。在一次小組同事間分享的時候,有位同事給出了這樣一個代碼:

if (true) {
    function fn() {
        alert('為 true 時執行我!');
    }
} else {
    function fn() {
        alert('為 false 時執行我!');
    }
}
fn()

大家可以看下,這段代碼執行的結果到底是什么?開啟你智慧的大腦吧!

好吧,下面是各主流瀏覽器的執行結果:

  1. 最愛的chrome:// 為 false 時執行我!
  2. 不用很久的firefox // 為 true 時執行我!
  3. IE7/8/9  // 為 false 時執行我!

哦,這是why?其實當我那同事問我們的時候,我的第一直覺就是 “為 true 時執行我!”。 后來,我想了想這個情況是不是瀏覽器在解析javascript的語法分析的時候有區別。

下面是我當時的猜想,大家不要當作是解釋以上代碼的理由:

1.chrome和IE在解析上述代碼的時候語法作用域解析的變量與函數聲明提升。大概是這樣的意思:

function fn() {
    alert('為 true 時執行我!');
}
function fn() {
    alert('為 false 時執行我!');
}        

if (true) {
    function fn() {
        alert('為 true 時執行我!');
    }
} else {
    function fn() {
        alert('為 false 時執行我!');
    }
}
fn()

所以后面的函數覆蓋前面的函數,所以才會是這樣的結果。

firefox的解析可能不太一樣,在處理語法作用域的時候,當函數聲明的時候在if語句中是按順序執行。

哈哈,以上也是自己的猜想,沒有去研究瀏覽器之間的源碼,能力有限,今日記下,日后有能 力再補上。也歡迎各路高手留言指點迷津。

分割,在我那個同事分享后放假就是五一,三天假期像我這樣的宅男只能看着別人帶着女朋友到處旅游;自個默默的只好宅在家里,三天休息也不是一點沒有收獲。三天有兩天下午到公園跑步跑6圈,不經常跑步,一跑起來真是上氣不接下氣,但還是堅持跑完了自己定下的6圈,畢竟做程序的沒有個好身體怎么行是吧?每晚,看會周愛民寫的《javascript語言精髓與編程實踐》,剛好看到模塊化的層次---語法作用域這一節,就有涉及上述代碼的解釋。

javascript語法作用域圖表:

 特殊作用運算符圖

在這一節的語法作用域之間的相關性是這樣描述的:

結構化語言中,代碼塊的作用域是相互不相交的。這些作用域之間只存在平行或嵌套兩種相關性。

例如:

代碼平行:

/**
* 示例1:代碼一與代碼二平行
*/

// 代碼一
if (true){
    // ...
}
// 代碼二
while (true) {
    // ...
}

代碼嵌套:

/**
* 示例2: 代碼一與代碼二嵌套
*/

// 代碼一
if (true){
    // ...
    // 代碼二
    while (true) {
        // ...
    }
}

結構化語言是通過代碼塊這種“互不相交”的特性來保證邏輯上的獨立,消除代碼塊之間的耦合。但是“嵌套”這種相關性中,代碼二與代碼一的語法作用域存在重疊。這種關系,就是通過前面所說的“語法作用域的級別”來控制。

  1. 相同級別的語法作用域可以相互嵌套
  2. 高級別的語法作用域能夠包含低級別的語法作用域
  3. 低級別的語法作用域不包含高級別的語法作用域。由於不存在包含關系,因此語言實現時,一般處理成語法的違例,或者理解為“平行”的關系。

規則一的示例:

/**
* 規則1: 相同級別的代碼的嵌套
*/
function fn1() {
    function fn2() {
        function fn3() {
            // ....
        }
    }
}

規則二的示例:

/**
* 規則2: 高級別代碼的嵌套低級別代碼
*/
function fn1() {
    if (true) {
        // ...
    }
}

規則三的示例:

/**
* 規則3: 低級別代碼的嵌套高級別代碼
*/
if (true) {
    function fn1() {
        // ...
    }
} else {
    function fn1() {
        // ...
    }
}

// 低級別代碼不能包含高級別代碼,所以把這種嵌套關系理解成平行關系

if (true) {
    // ..
} else {
    // ...
}

function fn1() {
    // ...
}

function fn1() {
    // ...
} // 同名函數,后者覆蓋前者

至此,大家看到規則三的時候是不是很眼熟啊,的確,看到這示例就很快能理解之前我同事分享那段代碼在chrome和IE的執行結果是怎么一回事。

不過遺憾的是,沒能解釋為什么在firefox的執行原理,正如我前面個人的猜想的那樣吧,只不過目前自己還沒弄清在firefox的執行原理,不過那是遲早的事兒。還是那句話,歡迎大家不要吝惜自己的留言,把自己理解的分享給大家也是在提升自己。^_^!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM