原型模式故事鏈(5)--JS變數作用域、作用域鏈、閉包

weixin_33807284發表於2018-10-27

上一章 JS執行上下文、變數提升、函式宣告 傳送門:https://segmentfault.com/a/11...

本次我們主要講講變數作用域和閉包
變數作用域:
顧名思義:變數起作用的範圍。
變數分為全域性變數和區域性變數。
全域性變數:在任何地方都能用,在所有函式之外。
區域性變數:只能在定義它的函式中,以及它的子函式中使用。

當前作用域沒有定義的變數,稱為自由變數。

舉例子:

<!DOCTYPE html>
<html>
<head>
    <title>dsfg</title>
</head>
<body>
<script type="text/javascript">
    var g = 'globle';
    function fn(){
        var p = 'part';    
        console.log(g);//globle
        console.log(p);//part
    }
    fn();
    console.log(g);//globle
    console.log(p);//報錯: p is not defined
</script>
</body>
</html>

在上述例子中,g是全域性變數,不存在於任何函式中,能在任何地方使用。
p則是區域性變數,只能在fn函式中使用。在外部使用則會報錯。

作用域鏈:
函式的變數在尋找作用域時,不看在哪執行,只看在哪定義。

舉例子:

<!DOCTYPE html>
<html>
<head>
    <title>dsfg</title>
</head>
<body>
<script type="text/javascript">
    var a = 100;
    function fn1(){
        var b = 200;
        
        function fn2(){
            var c = 300;
            console.log(a);//100
            console.log(b);//200
            console.log(c);//300
        }
        fn2();
    }
    fn1();
</script>
</body>
</html>

以變數a來解析,上述例子中體現的作用域鏈。當執行console.log(a)時,先在fn2中尋找變數a,找不到則去到fn2的父級fn1中尋找,也找不到。再到fn1的父級中尋找,也就是全域性變數中尋找,終於找到了。像這樣一層一層向上查詢,就叫變數作用域鏈。
如果在其中任何一層找到了,則不會繼續向上查詢。

閉包:
下個定義:可以訪問另一個函式作用域變數的函式。所以閉包其實是個函式。

為什麼要用閉包呢?
區域性變數無法共享和長久的儲存,全域性變數則很容易造成變數汙染。閉包則能長久儲存變數,又不會汙染。
閉包特點:佔用更多記憶體,不容易被釋放。
閉包使用場景:1.函式作為返回值(retrun 一個函式)

         2.函式作為引數傳遞到另一個函式中。

舉例子:

<!DOCTYPE html>
<html>
<head>
    <title>lalala</title>
</head>
<body>
<script type="text/javascript">
    function fn(){
        var a = 100;
        return function(){
            console.log(a);
        }
    }
    var f1 = fn();
    var a = 200;
    f1();//100
</script>
</body>
</html>

1.定義外層函式,封裝被保護的區域性變數。
2.定義內層函式,執行對外部函式的變數操作。
3.外層函式返回內層函式的物件,且外層函式被呼叫時,結果儲存在一個全域性變數中。

執行f1()時,a在當前函式中未定義,往父級查詢fn中a=100,所以a=100;
函式變數作用域不看在哪執行,只看在哪定義

好啦好啦,jS三座大山翻過兩座了,還剩一個非同步,單執行緒~

相關文章