以前一直对js的闭包不是很理解,看了很多文章也理解不了,果然我是个辣鸡前端,直到最近在看防抖,网上很多防抖的方法都一样,现在以滚动为例子:
// 防抖
function debounce(f, wait) {
var timer = null;
return function() {
if(timer !== null) clearTimeout(timer);
timer = setTimeout(f, wait);
}
}
// 滚动后处理函数
function handle() {
console.log('滚动后执行的代码逻辑' + Math.random());
}
// 绑定滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
防抖的原理是:先设置一个定时器变量,用闭包保存,在事件触发的时候,清除定时器,然后再设置一个,那么如果页面一直滚动,刚刚建立的定时器就会被清除,直到最后不再滚动页面,就执行最后一次设置的定时器。
然后,之前一直不是很理解闭包的我更加不理解防抖原理,这是我的错误理解:每次滚动每次都调用了debounce,那定时器也被重新定义了,上一次的定时器怎么处理,怎么实现的上一次的定时器被清空,为什么为什么。。。。。
太难受了,又重新去看闭包的文章,醍醐灌顶!!!
滚动事件绑定的实际上是debounce函数return的那个匿名函数,就是个闭包,实现了对变量timer的静态化(每次调用都可以引用到之前的timer),和局部化(避免了对全局命名空间的污染),所以才能实现清空上次定时器防抖的功能。
那么闭包是怎么定义的,大多数就是一句话:有权访问另一个函数作用域内变量的函数都是闭包。举个栗子:
function test(){
var count = 0;
function counter(){
count++;
console.log(count);
}
return counter;
}
var someCount = test();
someCount();
someCount();
这里打印出来的分别是1、2,
var someCount = test()这一句中,test()返回的是counter,可以这么理解someCount = counter;(只是这么理解,并不能这么用!)
那么someCount()相当于counter();( ()是执行函数的意思 )
所以,变量count并没有被清掉,每次调用返回的都是叠加后的值。
总结:上面提到过的,闭包实现了对变量的静态化和局部化。
(个人理解,如有错误,感谢指正!)
网友评论