天天看點

JavaScript閉包閉包

版權聲明:本文為部落客原創文章,轉載請注明出處。 https://blog.csdn.net/twilight_karl/article/details/60592592

閉包

1,閉包可以讓局部變量駐留在記憶體中,而不會重複初始化

2,過度使用會導緻記憶體占用過高,是以用完後應及時解除引用:

b = null
function add(){
            var num = 100;
            return function(){
                return num++;
            };
        };

        var fun3 = add();   // 獲得閉包函數,add函數隻初始化一次
        alert(fun3());      // 101
        alert(fun3());      // 102
        alert(fun3());      // 103
        alert(fun3());      // 104
        fun3 = null;        // 過多的使用閉包會占用大量記憶體,使用完後要釋放閉包函數:
        alert(fun3());      // 報錯           

以循環裡的匿名函數的取值為例,分三種情況:

<1>: 傳回的閉包函數由于是在sum執行完後再執行,是以傳回的值都是5.數組中儲存的是匿名函數,需要用函數的方式調用。

// 001  
        function sum(){
            var arr = new Array();
            for(var i=0;i<5;i++){
                arr[i] = function(){
                    return i;
                }
            };

            return arr;
        };

        var data = sum();
        for( var i=0;i<5;i++){      // 全部是5
            alert(data[i]());
        }           

<2>: 利用函數的自我執行即時的給數組指派,傳回的數組内容是數字

// 002 
        function sum(){
            var arr = new Array();
            for(var i=0;i<5;i++){
                arr[i] = (function(num){        // 匿名函數的即時執行
                    return num;
                })(i);
            };

            return arr;
        };

        var data = sum();
        for( var i=0;i<5;i++){      // 正常
            alert(data[i]);
        }           

<3>: 使用函數的自我執行的同時傳回一個匿名函數,傳回的數組需要當成函數調用

// 003 
        function sum(){
            var arr = new Array();
            for(var i=0;i<5;i++){
                arr[i] = function(num){     // 匿名函數的即時執行
                    return function(){
                        return num; 
                    };
                }(i);
            };

            return arr;
        };

        var data = sum();
        for( var i=0;i<5;i++){      // 正常
            alert(data[i]());
        }           

閉包中的this

閉包中的this指向window,閉包并不屬于某個對象的屬性和方法。解決方法:對象冒充。

var flag = "window";

    var box = {
        flag : "box",
        fun : function(){
            return function(){
                return this.flag;
            }
        }
    };
    alert(box.fun()());     // 閉包的this指向window           

可以使用以下的方法解決,不直接使用閉包中的this,而是儲存普通函數中的this,再在閉包中調用:

var box2 = {
        flag : "box",
        fun : function(){
            var sss = this;
            return function(){
                return sss.flag;
            }
        }
    };
    alert(box2.fun()());        // box2           

使用call或者apply更改作用域也可以解決問題:

var box3 = {
        flag : "box",
        fun : function(){
            return function(){
                return this.flag;
            }
        }
    };

    alert(box3.fun().call(box3));           

私有作用域

JavaScript沒有塊級作用域,但是自我執行的匿名函數有私有作用域,作用域中的變量在執行完後就被銷毀,在作用域外無法被調用。可以減少全局變量的使用。

(function(){
        for(var i=0;i<5;i++){}
    })();
    alert(i);       // undefined           

私有變量

this.屬性或this.方法表示的是共有方法和屬性。但是在方法中用var聲明的方法或屬性是私有屬性,外部無法調用,用該函數建立的對象也無法使用私有屬性。

function Person(str){
            var name = str;         // 私有屬性
            var fun = function(){   // 私有方法
                return name+"###";
            };
        };
        var tom = new Person("Tom");

        alert(tom.fun());       // 報錯
        alert(tom.name);        // 報錯           

繼續閱讀