閉包堆棧的小題

寫出執行以下代碼的結果:

function fun(n, o) {
            console.log(o);
            return {
                fun: function (m) {
                    return fun(m, n);
                }
            };
        }
        var c = fun(0).fun(1);
        c.fun(2);
        c.fun(3);

代碼運行的過程,在以下代碼中:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>閉包堆棧的小題</title>
</head>

<body>
    <script>
        function fun(n, o) {
            console.log(o);
            return {
                fun: function (m) {
                    return fun(m, n);
                }
            };
        }
        var c = fun(0).fun(1);
        c.fun(2);
        c.fun(3); //=> undefined 0 1 1
        // 輸出結果爲:undefined 0 1 1,執行過程如下:
        /*
            ECSTack:
            EC(G):
                VO(G):
                    Fun ,創建一個變量fun,並且創建一個堆,並將這個堆賦值給Fun,Fun = AAAFFF000。
                    var c = fun(0).fun(1); =>先創建變量c,然後執行fun(0),而後將結果.fun(1)執行,最後將這個結果賦值給變量c。執行結果如下:
                    因爲是函數,所以會創建有一個新的執行上下文,稱爲EC(FUN)1,也就是fun(0),裏面的內容爲:
                        變量對象:AO(FUN)1;作用域鏈爲:<--,VO(G)>
                            傳遞的實參個數,arguments=1
                            形參賦值:
                                n = 0,
                                o = undefined
                        代碼執行:
                        console.log(o) =>undefined
                        return {fun:function(m){return fun(m,n)}},在此返回一個對象,創建一個新的堆對象,名爲AAAFFF111,fun(0)執行後,要執行"結果.fun(1)",即AAAFFF111.fun(1),會產生一個新的執行上下文,anonymous是匿名的意思,可以稱上下文爲EC(AM)1,裏面的內容爲:
                            創建變量對象AO(AM)1 ; 作用域鏈<AO(AM)1,AO(FUN)1>
                                傳遞的實參個數,arguments=1
                                形參賦值:m=1
                                代碼執行:return fun(m,n),m是1,而n本作用域沒有,向上級找,在AO(FUN)1
中,n爲0,=>所以是return fun(1,0),先執行fun(1,0).然後將這個的函數結果返回,故創建新的上下文,再一次執行fun():
        EC(FUN)2:=> fun(1,0)
            創建變量:AO(FUN)2;作用域鏈:<AO(FUN)2,VO(G)>,上級作用域鏈是找在哪裏創建的,Fun是在全局創建的所以,是VO(G)
                傳遞的實參個數,arguments=2
                形參賦值:
                    n:1,
                    o:0
            代碼執行:
                console.log(o)=>0
                return {
                    fun:function(){...}
                },返回一個對象,在此是將這個返回的結果給c,所以這個return對象就是c,因是在AO(FUN)2中創建的,上級作用域就是AO(FUN)2。
            c.fun(2);=>執行c中的fun函數,會創建新的執行上下文,EC(AM)2,傳個2 => AM(2):
                創建變量對象AO(AM)2;作用域鏈:<AO(AM)2,AO(FUN)2>
                    傳遞的實參個數:arguments=1;
                    形參賦值:m=2;
                    代碼往下執行:
                        return fun(m,n)=> m是2,n在本作用域中沒有,向上級查找,就是AO(FUN)2中,n=1,即return fun(2,1),要執行fun(2,1),然後將執行結果返回,所以就是fun()第三次執行,會形成新的執行上下文,即EC(FUN)3: => fun(2,1)
                            裏面的執行:
                                創建新的變量對象AO(FUN)3;作用域鏈爲<AO(FUN)3,VO(G)>因爲fun是在全局創建,所以上級爲VO(G)。
                                fun(2,1) => 因爲在上述代碼中直接return fun(m,n),即fun(2,1),接下來就是執行fun(2,1):
                                    傳遞的實參個數爲:arguments=2
                                    形參賦值:
                                        n:2,
                                        o:1
                                    代碼執行:
                                        console.log(o) =>1
                                        return{
                                            fun:function(){...}
                                        }
            c.fun(3)=>執行c中的fun函數,會創建新的執行上下文,EC(AM)3,傳個3 => AM(3):
                創建變量對象AO(AM)3;作用域鏈:<AO(AM)3,AO(FUN)2>
                    傳遞的實參個數:arguments=1;
                    形參賦值:m=3;
                    代碼往下執行:
                        return fun(m,n)=> m是3,n在本作用域中沒有,向上級查找,就是AO(FUN)2中,n=1,即return fun(3,1),要執行fun(3,1),然後將執行結果返回,所以就是fun()再次執行,會形成新的執行上下文,即EC(FUN)4: => fun(3,1)
                            裏面的執行:
                                創建新的變量對象AO(FUN)4;作用域鏈爲<AO(FUN)4,VO(G)>因爲fun是在全局創建,所以上級爲VO(G)。
                                fun(3,1) => 因爲在上述代碼中直接return fun(m,n),即fun(2,1),接下來就是執行fun(3,1):
                                    傳遞的實參個數爲:arguments=2
                                    形參賦值:
                                        n:3,
                                        o:1
                                    代碼執行:
                                        console.log(o) =>1
                                        return{
                                            fun:function(){...}
                                        }

        */
    </script>
</body>
</html>

如下圖:
堆棧小題運行過程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章