1. 程式人生 > >從零開始學習前端JAVASCRIPT — 14、閉包與繼承

從零開始學習前端JAVASCRIPT — 14、閉包與繼承

註意 退出 二次 需要 正常 def 解決 doc span

1:閉包

1 . 概念:閉包就是能夠讀取其他函數內部變量的函數。在JS中,只有函數內部的子函數才能讀取局部變量,因此可以把閉包簡單理解為”定義在一個函數內部的函數”。

2 . 閉包的特點

1)可以讀取函數內部的變量。

2)讓這些變量的值始終保存在內存中。

3 . 閉包的原理

理解閉包,首先必須理解JS變量的作用域。變量的作用域無非就是兩種(es5):全局變量和局部變量。

JS語言的特殊之處,就在於函數內部可以直接讀取全局變量。另一方面,函數外部自然無法讀取函數內的局部變量。

註意:

1)函數內部聲明變量的時候,一定要使用var聲明。如果不用的話,你實際上聲明了一個全局變量。

2)局部變量的作用域,在函數定義的時候就已經確定下來了。

出於各種原因,我們有時候需要得到函數內部的局部變量。但是正常情況下這是辦不到的。只有變通一下才能實現,那就是在函數內部再定義一個函數。外部變量不能訪問內部變量,內部變量卻能訪問外部變量,這正是因為JS特有的”鏈式作用域”結構(chain scope),子對象會一級一級地向上尋找所有父對象的變量。所以父對象的所有變量,對子對象都是可見的,反之則不成立。我們只需要把子函數返回出來,我們就可以在外部讀取內部變量了。

4 . 閉包的應用場景

1)函數作為返回值。

<!DOCTYPE html>
<html lang="
en"> <head> <meta charset="UTF-8"> <title>閉包</title> </head> <body> <script> function f1() { var n = 999; nAdd = function () { n += 1; } function f2() { console.log(n) }
return f2; } var result = f1(); console.log("result的第一次執行") result();//999 console.log("nAdd的執行") nAdd();//無輸出 console.log("result的第二次執行") result();//1000 </script> </body> </html>

  2)函數作為參數被傳遞。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>閉包</title>
</head>
<body>
    <script>
        function fun(n, o) {
            console.log(o);
            return {
                fun: function (m) {
                    return fun(m, n);
                }
            };
        }
        var a = fun(0); //undefined
        // 執行完並未銷毀保存在內存中
        a.fun(1); //0
        a.fun(2); //0
        a.fun(3); //0

        fun(0).fun(1).fun(2).fun(3);
        //undefined、0、1、2
        var a = fun(0).fun(1); 
        //undefined、0
        a.fun(2); 
        //undefined、1
        a.fun(3);        
        //undefined、1
    </script>        
</body>
</html>

5 . 使用閉包註意點

1)由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包。否則會造成網頁性能問題,在IE中可能導致內存泄漏。解決方法就是在函數退出之前,將不使用的局部變量刪除(值置為null,垃圾回收機制就會處理)

2)閉包會在父函數外部,改變父函數內部變量的值。所以不要隨便改變父函數內部變量的值。

6 . demo通過js閉包實現鼠標滑過隔行換色的效果


2:構造函數的繼承

從零開始學習前端JAVASCRIPT — 14、閉包與繼承