天天看點

JavaScript作用域問題

        JavaScript的作用域問題是一個比較複雜的問題也是在編寫程式過程中比較容易出錯的地方,特别是從C/C++這些具有塊級語言功能的語言轉過來的工程師。

       JavaScript在ES6時代之前是沒有塊級作用域的概念隻有全局作用域和函數級作用域這兩種作用域。同時由于JavaScript定義變量的特殊性導緻編寫程式的時候容易出現一些問題造成不少的麻煩。

      JavaScript定義變量的特殊性:

(1)使用var定義變量的時候會産生變量提升。

(2)使用var定義變量的時候,允許在同一作用域下多次使用var來進行聲明變量,但是隻有第一次是進行聲明變量,剩下的是進行指派操作。

(3)在對值進行指派的時候,先會在目前作用域下檢視是否有此變量的聲明,如果有進行變量的指派,如果沒有就向上一級作用域進行查找,查找到就對其進行指派,如果沒有查找到将在全局的作用域下進行指派。

<!DOCTYPE html>
<html>
    <head>
        <title>變量的作用域問題</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script>
            var name="apple"
            var name="watermelon"
            function say(){
                console.log(name);
                if(1){
                    var name="banana"
                }
                console.log(name);
                name="orange";
                console.log(name);
            }
            say();
            console.log(name);
        </script>
    </body>
</html>
           

上述程式輸出的結果依次是:

undefined

banana

orange

watermelon

當對程式進行修改之後

<!DOCTYPE html>
<html>
    <head>
        <title>變量的作用域問題</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script>
            var name="apple"
            var name="watermelon"
            function say(){
                console.log(name);
                if(1){
                    name="banana";
                    age=24
                }
                console.log(name);
                name="orange";
                console.log(name);
            }
            say();
            console.log(name);
            console.log(age);
        </script>
    </body>
</html>
           

程式輸出的結果依次是:

watermelon

banana

orange

orange

通過上述的兩個程式可以看出這兩個函數在作用域上的差別:由于第一個程式中是使用var聲明的變量是以會在函數作用域中建立name變量,不使用var聲明變量将會使用上一級的name變量。

JavaScript作用域問題

通過說明ES5前作用域的問題,暴露了ES5編寫程式的緻命問題,如果忘記使用var在函數作用域中聲明變量将會使得全局作用域下同名變量被修改。這樣的話是不利于編寫大規模的程式,同時也是由于這個原因也需要提供塊級作用域,以避免函數作用域中和全局作用域中變量污染 和變量不夠的問題,是以ES6提出了let和const的塊級作用域的函數的聲明以解決var聲明的問題。

(1)沒有變量的提升

(2)同一作用域下不能進行多次對同一變量的聲明

(3)提供塊級作用域

<!DOCTYPE html>
<html>
    <head>
        <title>變量的作用域問題</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script>
            let name="apple"
            function say(){
                console.log(name);
                if(1){
                    let name="banana";
                }
                console.log(name);
                name="orange";
                console.log(name);
            }
            say();
            console.log(name);
            console.log(age);
        </script>
    </body>
</html>
           

當程式這樣編寫的時候會輸出:

apple

apple

orange

orange

出現這樣的情況是由于let聲明的name函數隻在if形成的塊級作用域中有效。

繼續閱讀