什么是闭包
闭包是嵌套的内部函数;内部函数包含被引用变量(函数)的对象。闭包存在于嵌套的内部函数中,例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来。
如何产生闭包
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
闭包的应用
定义JS模块(具有特定功能的js文件),将所有的数据和功能都封装在一个函数的内部(私有的),只向外暴露一个包含n个方法的对象和函数;模块的使用者只需要通过模块暴露的对象调用方法来实现对应的功能。
//myModule.js 文件
function myModule(){
// 私有数据
var msg = 'My Module'
function showUpper(){
console.log('showUpper' +msg.toUpperCase());
}
function showLow(){
console.log('showLow' +msg.toLowerCase());
}
//向外暴露对象(给外部使用的方法)
return {
showUpper:showUpper,
showLow:showLow
}
}
//index.html文件
<script src="./myModule.js"></script>
<script>
var module = myModule()
module.showUpper()
module.showLow()
</script>
闭包就是能够读取其它函数内部变量的函数。 在js中,只有函数内部的子函数才能读取局部变量
因此可以把闭包简单粗暴地理解成“定义在一个函数内部的函数”,即一个函数嵌套了另一个函数。
作用
1.读取函数内部的变量
2.令这些变量的值始终保持在内存中
function f1(){
var n = 'RORO彦';
add=function(){n = 'RORO';};
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // RORO彦
add();
result(); // RORO
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次是RORO彦,第二次是RORO。函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除,而是保存在内存堆(heap)里, 原因是它被包装或封装在一个函数体内,这些构造器都被称为闭包。它返回调用函数的运行结果,是函数本身。此外,add的值是一个匿名函数,它本身也是一个闭包,所以add相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
注意事项
函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。闭包会在父函数外部改变父函数内部变量的值。所以,当你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,不要随便改变父函数内部变量的值。
闭包的应用:
闭包实现模块化、封装变量
// 闭包实现模块化、封装变量
const useName = function(){
var name = 'qq'
function publicMethod(){
console.log('publicMethod,name:',name)
}
function privateMethod(){
console.log('privateMethod')
}
return {
name,
publicMethod
}
}()
useName.publicMethod()
经典for循环变量输出问题用闭包来解决
for(var i=0;i<5;i++){
(function(i){
setTimeout(function(){
console.log(i)
},1000)
})(i)
}