08-JavaScript作用域和預(yù)解析

作用域

  • JavaScript中作用域的概念和C語言一樣, 也分為全局作用域和局部作用域
  • 全局作用域
    • 在任何地方都可以訪問到的就是全局作用域
    • 在script標(biāo)簽中或一個(gè)獨(dú)立js文件中定義的就是全局作用域
<script>
    var num = 10; // 該變量是全局作用域
    function test() { 
        // 在函數(shù)中訪問全局作用域num變量
        console.log("test中"+num);
    }
    test();
    // 在外面訪問全局作用域num變量
    console.log("外部"+num);
</script>
    function test() { // 該函數(shù)是全局作用域
        console.log("test函數(shù)");
    }
    // 在外面訪問全局作用域test函數(shù)
    test();
    function demo() { 
        // 在函數(shù)中訪問全局作用域test函數(shù)
        test();
    }
    demo();
  • 局部作用域
    • 只在固定的代碼片段內(nèi)可訪問到的變量,例如函數(shù)內(nèi)部。對(duì)應(yīng)局部作用域(函數(shù)作用域)
    • 寫在函數(shù)內(nèi)部的都是局部作用域, 只能在當(dāng)前函數(shù)內(nèi)訪問
<script>
    function test() {
        var num = 123; // 該變量是局部作用域
        // 可以在同一個(gè)局部作用域中訪問
        console.log("test中"+ num);
    }
    // 不能在局部范圍以外訪問
    console.log("外部"+num);
</script>
<script>
    function test() {
        function demo() { // 該函數(shù)是局部作用域
            console.log("demo函數(shù)");
        }
        // 可以在同一個(gè)局部作用域中訪問
        demo();
    }
    // 不能在局部范圍以外訪問
    demo();
</script>
  • 注意點(diǎn):
  • 如果在函數(shù)中定義變量時(shí),如果不添加var關(guān)鍵字, 這個(gè)變量是一個(gè)全局變量
<script>
    function test() {
        // 企業(yè)開發(fā)千萬不要這么寫
        num = 123;
        console.log(num);
    }
    test();
    console.log(num);
</script>
  • 任何一對(duì)花括號(hào)({和})中的語句集都屬于一個(gè)塊,在這之中定義的所有變量在代碼塊外都是不可見的,我們稱之為塊級(jí)作用域。
  • 在es5之前沒有塊級(jí)作用域的的概念,只有函數(shù)作用域,現(xiàn)階段可以認(rèn)為JavaScript沒有塊級(jí)作用域

作用域鏈

  • JavaScript代碼中至少有一個(gè)作用域, 即全局作用域。
  • 凡是代碼中有函數(shù),那么這個(gè)函數(shù)就構(gòu)成另一個(gè)作用域。
  • 如果函數(shù)中還有函數(shù),那么在這個(gè)作用域中就又可以誕生一個(gè)作用域。
  • 將這樣的所有的作用域列出來,可以形成的結(jié)構(gòu)就稱之為作用域鏈。
<script>
    var num = 123; // 0級(jí)作用域鏈
    function test() { // 0級(jí)作用域鏈
        var num = 666; // 1級(jí)作用域鏈
        console.log(num);
        function demo() { // 2級(jí)作用域鏈
            var num = 777;
            console.log(num);
        }
        demo();
    }
    test();
    console.log(num);
</script>

再直白一點(diǎn): 訪問時(shí)就是C語言中的就近原則


預(yù)解析

  • JavaScript代碼的執(zhí)行是由瀏覽器中的JavaScript解析器來執(zhí)行的。
  • JavaScript解析器執(zhí)行JavaScript代碼的時(shí)候,分為兩個(gè)過程:
    • 預(yù)解析過程
    • 代碼執(zhí)行過程
  • 預(yù)解析過程:
      1. 把變量的聲明提升到當(dāng)前作用域的最前面,只會(huì)提升聲明,不會(huì)提升賦值。
      1. 把函數(shù)的聲明提升到當(dāng)前作用域的最前面,只會(huì)提升聲明,不會(huì)提升調(diào)用。
      1. 先提升var,在提升function。
  • 案例1
<script>
    console.log(num); // undefined
    var num = 123;
</script>
<script>
    // 把變量的聲明提升到當(dāng)前作用域的最前面
    var num;
    console.log(num);
    num = 123;
</script>
  • 案例2:
<script>
    test();
    function test() {
        console.log("hello world");
    }
</script>
<script>
    test();
    alert(test);
    function test() {
        console.log("hello world");
    }
</script>
<script>
    // 把函數(shù)的聲明提升到當(dāng)前作用域的最前面
    function test() {
        console.log("hello world");
    }
    test();
    alert(test);
</script>
  • 預(yù)解析練習(xí)
    var num = 123;
    fun();
    function fun() {
        console.log(num);
        var num = 666;
    }
    /*
    var num;
    function fun() {
        var num;
        console.log(num);
        num = 666;
    }
    num = 123;
    fun();
    */
    var a = 666;
    test();
    function test() {
        var b = 777;
        console.log(a);
        console.log(b);
        var a = 888;
    }
    /*
    var a;
    function test() {
        var b;
        var a;
        b = 777;
        console.log(a);
        console.log(b);
        a = 888;
    }
    a = 666;
    test();
    */
  • 注意點(diǎn):
    • 變量和函數(shù)同名時(shí), 函數(shù)的優(yōu)先級(jí)高
<script>
    console.log(num);
    function num() {
        console.log("hello world");
    }
    var num = 666;
    console.log(num);

    /*
    function num() {
        console.log("hello world");
    }
    var num;
    console.log(num);
    num = 666;
    console.log(num);
     */
</script>

不同方式定義函數(shù)區(qū)別

  • 預(yù)解析時(shí)提升的方式不同
<script>
    // 1.函數(shù)聲明
    test();
    function test() {
        console.log("指趣學(xué)院");
    }
    // 2.函數(shù)表達(dá)式
    demo(); // 報(bào)錯(cuò)
    var demo = function () {
        console.log("www.it666.com");
    }
    /*
    function test() {
        console.log("指趣學(xué)院");
    }
    var demo;
    test();
    demo();
    demo = function () {
        console.log("www.it666.com");
    }
     */
</script>
  • 新舊版本瀏覽器預(yù)解析處理方式不同
<script>
    /*
    在新版本瀏覽器中, 代碼塊中的函數(shù)不會(huì)被提升
    在舊版本瀏覽器中, 代碼塊中的函數(shù)會(huì)被提升
    新版本輸出"指趣學(xué)院"
    老版本輸出"www.it666.com"
     */
    if(true){
        function test() {
            console.log("指趣學(xué)院");
        }
    }else{
        function test() {
            console.log("www.it666.com");
        }
    }
    test();
</script>
<script>
    var test;
    if(true){
        test = function () {
            console.log("指趣學(xué)院");
        }
    }else{
        test = function() {
            console.log("www.it666.com");
        }
    }
    test();
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容