闭包的理解

先放一个题外话:
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
    

用处:闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

注意点:

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值

工欲善其事 必先利其器
原文地址:https://www.cnblogs.com/fengyouqi/p/9565997.html