JavaScript - 運行機制,做用域,做用域鏈(Scope chain)

參考

https://www.jianshu.com/p/3b5f0cb59344
https://jingyan.baidu.com/article/4f34706e18745be386b56d46.html
https://www.2cto.com/kf/201401/273825.html
http://www.javashuo.com/article/p-apunkzvq-eh.htmlhtml

運行機制

JavaScript代碼的執行是由瀏覽器中的JavaScript解析器來執行的。JavaScript解析器執行JavaScript代碼的時候,分爲兩個過程:預解析過程和代碼執行過程。即先解析(例如先進行變量、函數的聲明提高),後運行。瀏覽器

JavaScript 運行分爲兩個階段:

- 預解析
  - 全局預解析(全部變量和函數聲明都會提早;同名的函數和變量函數的優先級高)
  - 函數內部預解析(全部的變量、函數和形參都會參與預解析)
    - 函數
    - 形參
    - 普通變量
- 執行

先預解析全局做用域,而後執行全局做用域中的代碼,

在執行全局代碼的過程當中遇到函數調用就會先進行函數預解析,而後再執行函數內代碼。

1. 預解釋/預處理,變量提高(Hoisting)

預解析過程:

  1. 把變量的聲明提高到當前做用域的最前面,只會提高聲明,不會提高賦值。
  2. 把聲明式函數(JS有賦值式函數/函數表達式var f = function(){},這個不能被提高)的聲明提高到當前做用域的最前面,只會提高聲明,不會提高調用。
  3. 先提高var,在提高function

打印2次2。由於foo()提高到當前做用域的頂部。函數

function foo() {
    console.log('1');
};

foo();

function foo() {
    console.log('2');
};

foo();

JS解釋器逐個塊(一個<script>就是一個塊)解釋。先到第一個<script>,f1提高到全局做用域(打印哈哈)。到第二個<script>,最新的function f1的聲明提高到全局做用域,固然執行最新的一個聲明(打印嘎嘎)。code

<script>
        function f1() {
            console.log("哈哈");
        }

        f1();
    </script>
    <script>
        f1();

        function f1() {
            console.log("嘎嘎");
        }
    </script>

    <script>
        f1();
    </script>

// 一、-----------------------------------
var num = 10;
fun();
function fun() {
  console.log(num);
  var num = 20;
}
//二、-----------------------------------
var a = 18;
f1();
function f1() {
  var b = 9;
  console.log(a);
  console.log(b);
  var a = '123';
}
// 三、-----------------------------------
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
  var a = b = c = 9;
  console.log(a);
  console.log(b);
  console.log(c);
}

2. 做用域

在ES5以前JS沒有塊級做用,有函數做用域。用函數做用域能夠避免多個<script>的全局變量污染。先能夠認爲JS通常沒有塊級做用域,有函數做用域。
塊級做用域: "{}內部聲明的變量只可以在{}內部訪問到,在{}外部沒法訪問到其內部聲明的變量"htm

3. 做用域鏈

當咱們在局部做用域中,訪問一個變量時,系統首先會在當前做用域中尋找變量var的聲明語句,如找到則直接使用。反之,則繼續向上一級做用域中尋找var的聲明語句,如找到則直接使用,反之,繼續向上一級做用域中去尋找…直到全局做用域blog

例子,嘗試註釋掉每一個f的num

<script>


        var num = 10;

        function f1() {
            var num = 20;

            function f2() {
                var num = 30;

                function f3() {
                    var num = 50;
                    console.log(num);
                }

                f3();
            }

            f2();
        }

        f1();
    </script>


4. 隱式全局變量

在function裏,用var定義的變量是局部變量;不用var定義的變量爲隱式全局變量ip

function f1() {
            var a;//局部變量
            a = 9;
            //隱式全局變量
            b = 9;
            c = 9;
            console.log(a);//9
            console.log(b);//9
            console.log(c);//9
        }

        f1();
        console.log(c);//  9
        console.log(b);// 9
        console.log(a);//報錯
相關文章
相關標籤/搜索