其实一直没搞懂闭包啥意思,然后看jquery基础最后有个对闭包的解释,看得半懂不懂的,试试用java解释下
有内部函数的外部函数好比是java里的一个class,当然是一个特殊的类,比如不能再class里直接System.out.println(),但是可以在外部函数里alert()
下面把外部函数改为父函数,比较好理解点
内部函数就好比java里的方法
js里要在外部调用内部函数,两种方法,要么全局变量引用,要么父函数返回
java里调用方法就很简单
到目前为止都是很正常的,其实这时候闭包已经创建了,书上对闭包的解释是:当内部函数(innerFn1)在定义它的作用域(outerFn)的外部被引用时(global.fn1();),就创建了一个闭包.
但是当父函数创建了个变量,且由内部函数调用,然后内部函数在父函数外调用,问题就来了
js中的outerVal如果没被调用就是普通的变量,当执行了方法后这个变量就会被回收
但是如果被内部变量(innerFn1)引用,并且这个内部变量又被外部引用执行(global.fn1())后,outerVal变量就成了一个类似于存在父函数(outerFn)中独有的全局变量,内存垃圾回收时不知道什么时候innerFn1还会引用,所以一直就不回收outerVal,一直放在内存里,就有点类似java中的static变量了,区别是java的static是程序启动的时候就创建了,这里的伪static变量是当闭包出现的时候才创建的。
简单来说:
父函数(outerFn)定义内部函数(innerFn1)。
没有闭包。内存正常回收
父函数(outerFn)定义内部函数(innerFn1),内部函数引用父函数的变量(outerVal)。
没有闭包。内存正常回收
内部函数(innerFn1)在父函数以外引用(global.fn1())。
闭包产生。内存正常回收(貌似不会正常回收,如果是被全局变量引用,那这个内部函数应该会常驻在内存中直到浏览器被关闭或者引用他的全局函数引用了其他值才会被回收吧)
当内部函数(innerFn1)调用了父函数(outerFn)的变量(outerVal),并且内部函数在父函数以外引用(global.fn1())。
闭包产生,并且outerVal变成类似存在于父函数中的全局变量(java中的static变量),内存不能正常回收。
有错的话请指正。
突然想到个问题,父函数的变量(outerVal)被内部函数调用,然后在父函数外引用导致不能回收内存,是因为在外部引用的变量(global)本身就是一个全局变量,就是说父函数的变量是被一个全局变量引用的,因为全局变量的作用域关系,当内存回收到这的时候自然会认为这个变量还在被引用是不能回收的,那如果我把全局变量手动赋值为null,就没有谁去引用这个父函数变量了,那这个父函数变量应该就会被回收了吧。不知道对不对。
有内部函数的外部函数好比是java里的一个class,当然是一个特殊的类,比如不能再class里直接System.out.println(),但是可以在外部函数里alert()
下面把外部函数改为父函数,比较好理解点
内部函数就好比java里的方法
js
function outerFn(){
function innerFn1(){
}
function innerFn2(){
}
}
java
public class outerFn{
public void innerFn1(){
}
public void innerFn2(){
}
}
js里要在外部调用内部函数,两种方法,要么全局变量引用,要么父函数返回
1:全局变量引用
var global=[];
function outerFn(){
function innerFn1(){
}
global.push(innerFn1);
}
执行
outerFn();//虽然是执行父函数,但是这里类似java里new了个新对象
global[0]();//类似java里调用对象里的方法
2:父函数返回
function outerFn(){
function innerFn1(){
}
...
return {'fn1':innerFn1,'fn2':innerFn2};
}
执行
var global=outerFn();
global.fn1();
global.fn2();
java里调用方法就很简单
outerFn outer=new outerFn()
outer.innerFn1();
outer.innerFn2();
到目前为止都是很正常的,其实这时候闭包已经创建了,书上对闭包的解释是:当内部函数(innerFn1)在定义它的作用域(outerFn)的外部被引用时(global.fn1();),就创建了一个闭包.
但是当父函数创建了个变量,且由内部函数调用,然后内部函数在父函数外调用,问题就来了
js
function outerFn(){
var outerVal=0;
...
}
java
public class outerFn{
private int outerVal=0;
...
}
js里outerVal是局部变量,java里outerVal是一个类的全局变量
js
然后内部函数调用
var outerVal=0;
innerFn1(){
outerVal++;
alert(outerVal);
}
return {'fn1':innerFn1};
...
var global=outerFn();
global.fn1();//1
global.fn1();//2
java
private int outerVal=0;
public void innerFn1(){
outerVal++;
System.out.println(outerVal);
}
outerFn outer=new outerFn()
outer.innerFn1();//1
outer.innerFn1();//2
js中的outerVal如果没被调用就是普通的变量,当执行了方法后这个变量就会被回收
但是如果被内部变量(innerFn1)引用,并且这个内部变量又被外部引用执行(global.fn1())后,outerVal变量就成了一个类似于存在父函数(outerFn)中独有的全局变量,内存垃圾回收时不知道什么时候innerFn1还会引用,所以一直就不回收outerVal,一直放在内存里,就有点类似java中的static变量了,区别是java的static是程序启动的时候就创建了,这里的伪static变量是当闭包出现的时候才创建的。
简单来说:
父函数(outerFn)定义内部函数(innerFn1)。
没有闭包。内存正常回收
父函数(outerFn)定义内部函数(innerFn1),内部函数引用父函数的变量(outerVal)。
没有闭包。内存正常回收
内部函数(innerFn1)在父函数以外引用(global.fn1())。
闭包产生。内存正常回收(貌似不会正常回收,如果是被全局变量引用,那这个内部函数应该会常驻在内存中直到浏览器被关闭或者引用他的全局函数引用了其他值才会被回收吧)
当内部函数(innerFn1)调用了父函数(outerFn)的变量(outerVal),并且内部函数在父函数以外引用(global.fn1())。
闭包产生,并且outerVal变成类似存在于父函数中的全局变量(java中的static变量),内存不能正常回收。
有错的话请指正。
突然想到个问题,父函数的变量(outerVal)被内部函数调用,然后在父函数外引用导致不能回收内存,是因为在外部引用的变量(global)本身就是一个全局变量,就是说父函数的变量是被一个全局变量引用的,因为全局变量的作用域关系,当内存回收到这的时候自然会认为这个变量还在被引用是不能回收的,那如果我把全局变量手动赋值为null,就没有谁去引用这个父函数变量了,那这个父函数变量应该就会被回收了吧。不知道对不对。