闭包 (closure)的讲解--应用案例(二)
1.1.1. 经典应用1:实现节流函数
在mui的buffer()函数中,我们提到了节流函数。节流函数就是一个函数在指定的时间间隔内,只能被调用一次。
例如,f函数,在1000ms内,只能调用一次。换句话,此时你调用f,则下一次再调用要等1000ms。本质上就降低函数执行的频率。
要求:1000ms内只能执行一次f.
改进如下:
上面的代码起到了降频的效果。
分析:
|
Var f = A():执行完成, 下面执行 Div.addEventListenter(“mousemove” ,f) 这一句执行之后,则如果鼠标在div上移动就会去调用f,
分析一下调用f的过程。 下面的代码就是f的函数体:
比较当前的时间与第一次保存的now的值之间是否>500( 表示时间过了500ms ).如果成立,则执行核心语句: Console.info(“鼠标移动中....”)
同时更新最近一次执行f的时间。Now = Date.now(); 由于now没有回收,所以它还可以正常访问的。
如果不成立(说明时间没有过500ms) |
1.1.1.1. 提炼一个节流函数
1.1.1.2. 用节流函数改一下鼠标移动的问题
1.1.2. 经典应用2:让一个函数只能被调用指定次数
1.1.3. 经典应用3
上面点击每一个li都会输出3
1.1.3.1. 解决办法 1:使用自定义属性
1.1.3.2. 解决办法 2:使用闭包
(1)iife。在function的前面有=号。
lis[i].onclick = function(index){}(i)
(2)闭包结构。
a) function的嵌套
b) 在子函数中,用到了index,而index是父函数的形参,就相当于是父函数的局部变量。所以 ,也就是在子函数中使用了父函数中定义的变量。
c) Return 子函数。
1.1. 闭包与内存泄漏
一般来说,在函数内部定义的变量,会随着函数的调用结束而被系统回收,如下:
Function f(){
Var i ;
}
F();
在F()执行完成后,i就不能再访问到了 。
由于闭包结构的存在,如下:
Function f(){
Var i ;
Return function(){
Console.info( i):
}
}
Var r = f();
R();
上面的代码中,由于r()在执行时,还需要用到变量i,这个变量i并不会被系统回收。
这种情况,我们不需要手动去回收变量(如在 c中,内存空间是可以手动回收的),js中内部有垃圾回收机制去做这件事,我们不需要管。
1.2. 闭包小结
还有很多其它的应用都是以闭包为基础的,如设计模式中的单例模式,面向对象的中,创建对象时,不使用new。
闭包比较难,大家要正确地使用。