防抖和节流
-
概念
-
防抖: 事件只在触发的N秒内,如果没有再次触发,则N秒后触发函数
-
节流: 事件在一定时间间隔内只执行一次
-
-
使用场景
- 防抖:input
- 节流:resize,scroll
-
手写一个节流函数
/** * 整个节流都有个最重要得特性,那就是闭包,闭包可以把函数里面得作用域带出来,这样可以让每次得start或者timer都是记忆得同一个得 */ // 时间戳写法(立刻执行的节流函数) function throttle(fn, millisecond) { let start = 0; // 先把开始时间定义为 0 return function () { let end = Date.now(); // 结束时间直接获取当前 if ((end - start) >= millisecond) { // 然后结束时间 减去 开始时间 如果是大于等于时间参数则可以执行(第一次肯定会立刻执行,因为start为0) start = end; // 这里结束时间 赋值 给开始时间,为一下次执行做准备 fn.apply(this, arguments); // 执行传来的函数,注意要用apply来改变this指向,因为你不知道这个返回的函数会使用在什么地方 } } } // 定时器写法(在传来的时间参数后执行的节流函数),会带来个问题,有可能最后一次点击会延迟执行 function throttle(fn, millisecond) { let timer = null; return function () { if (!timer) { timer = setTimeOut(() => { fn.apply(this, arguments); timer = null; }, millisecond) } } } // 混合写法 function throttle(fn, millisecond) { let timer; let start = Date.now(); return function() { let end = Date.now(); let duration = millisecond - (end - start); clearTimeout(timer); if (duration <= 0) { fn.apply(this, arguments); start = end; } else { timer = setTimeout(() => { fn.apply(this, arguments) }, duration) } } }
-
手写一个防抖函数
function antiShake(fn, millisecond) { let timer = null; return function() { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, millisecond) } } // 这里要注意一下clearTimeout和timer = null得区别,两者不能混用, // clearTimeout 是立刻暂停了定时器,但是不会清除对象本身 // timer = null 是清除对象本身,但是如果定时器已经开始执行,=null 也无法阻止本次执行