閉包

先放一個題外話:
node環境 親測結果: for(var i=0;i<5;i++){ setTimeout(function(){ console.log(i); },1000); } 每隔一秒輸出一個 5,共輸出五個5。 for(let i=0;i<5;i++){ setTimeout(function(){ console.log(i); },1000); } 每隔一秒輸出一個 數,0 1 2 3 4。

谷歌瀏覽器環境 親測結果:
for(var i=0;i<5;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}
先輸出一個10,而後每隔一秒輸出一個5,共輸出五個5。
for(let i=0;i<5;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}
先輸出一個5,而後每隔一秒輸出一個數,依次是0 1 2 3 4。
複製代碼
複製代碼
谷歌瀏覽器環境 親測結果:
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return function(){
            return this.name;
        };
    }
};
console.log(object.getNameFunc()());
輸出 "The Window"

console.log(object.getNameFunc().call(object));
輸出 "My Object"
複製代碼
複製代碼
這個相對簡單一點:
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};
console.log(object.getNameFunc()());
輸出 "My Object"
複製代碼
複製代碼
這兩個更簡單:
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : ()=>{
        console.log(this.name);
    }
};
object.getNameFunc();
輸出 The Window
undefined
var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        console.log(this.name);
    }
};
object.getNameFunc();
輸出 My Object
複製代碼
複製代碼
var name = 'global';

var obj = {
    name : 'obj',
    dose : function(){
        this.name = 'dose';
        return function(){
            return this.name;
        }
    }
}

console.log(obj.dose()());
輸出 global
console.log(obj.dose().call(this))
輸出 global
console.log(obj.dose().call(window))
輸出 global
console.log(obj.dose().call(obj))
輸出 dose

注意:把下面一行拆分(相似的均可以拆分)
obj.dose().call(this)
拆分爲:
var xxx = obj.dose();
xxx.call(this);
複製代碼
複製代碼
var name = 'global';

var obj = {
    name : 'obj',
    dose : function(){
        this.name = 'dose';
        return function(){
            return this.name;
        }.bind(this)
    }
}

console.log(obj.dose().call(this));
輸出 obj
注意:因爲return的function中用了bind,因此至關於固定了this,外邊再call什麼進來,也只是礙眼法而已。IE認爲在return中用bind不常見,兼容性也不高,因此上面內容能夠改寫以下:
var name = 'global';

var obj = {
    name : 'obj',
    dose : function(){
        var that = this;
        this.name = 'dose';
        return function(){
            return that.name;
        }
    }
}

console.log(obj.dose().call(this));
輸出 obj
    
複製代碼

用處:閉包能夠用在許多地方。它的最大用處有兩個,一個是前面提到的能夠讀取函數內部的變量,另外一個就是讓這些變量的值始終保持在內存中。node

注意點:瀏覽器

1)因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。閉包

2)閉包會在父函數外部,改變父函數內部變量的值。因此,若是你把父函數看成對象(object)使用,把閉包看成它的公用方法(Public Method),把內部變量看成它的私有屬性(private value),這時必定要當心,不要隨便改變父函數內部變量的值函數

來源:我將枕中記憶抹去任歲月浮光掠影性能

相關文章
相關標籤/搜索