闭包的理解
先放一个题外话:
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),这时一定要小心,不要随便改变父函数内部变量的值
工欲善其事 必先利其器