闭包一般就是函数套函数。里面的函数一般都当作返回值。
变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
函数内可以根据链式作用域先访问函数内的变量,找不到在逐级向外找。
如何产生闭包?
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量时,就产生了闭包。
函数内部引用了外部函数的(变量/函数),并执行了外部函数。
function fn1(){
var a = 2
var b = '123'
// 执行函数定义就会产生闭包(不用调用fn2函数)
function fn2(){
//fn2引用了fn1的变量a,此时就产生了闭包
console.log(a)
}
}
闭包 外部不能访问到内部的变量和方法,
闭包的作用
- 闭包可以延长函数内的局部变量的存活时间,函数执行完后,局部变量仍可以存活在内存中。
- 在函数外部可以访问函数内部的局部变量
- 闭包外部 不能访问闭包内部的变量和方法,起到隔离的作用。
正常情况下,函数中存在变量,函数执行完局部变量会被垃圾回收机制销毁。
function fn1(){
var a = 2
function fn2(){
a ++
console.log(a)
}
function fn3(){
a--
console.log(a) //因为使用了a 产生了闭包
}
return fn3
}
// 变量f接收了 函数对象fn3,暂存了fn3
var f = fn1()
f() // 1
f() // 0
闭包的缺陷
- 闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。
- 如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
闭包可以缓存局部变量
正常情况下闭包中的局部变量用完既被销毁,但是可以通过闭包延长变量存活时间。
function fn1(){
var a = 1;
function fn2(){
return a;
}
return fn2
}
var b = fn1();
b(); // 1
通过闭包解决问题
for(var i = 0;i<10;i++){
(function(j){
alert(i); // 打印 0 , 1 , 2 .....
})(i);
}
通过闭包模块化
(function(){
var a = 1;
function add(){
a ++;
}
var b = {}
b.add = add
window.a = b
})()
//调用 window.a.add();