JS: 防抖节流
防抖节流
防抖(debounce)
先来看看下面的代码:
//触发滚动事件,num 就加1
let num = 0; function incNum() {
console.log('鼠标滚动中');
console.log(`${num++} ${Date().getSeconds()}s`);
} window.addEventListener('scroll', incNum, false);
当滚动鼠标,
num会疯狂加1,从下图中可以看到稍微滚动一下鼠标就输出了N个num。
什么是防抖?
防抖指的是让某些代码不可以在没有间断的情况下连续重复地执行。举个例子,一部电梯开门等待30s就会关门上升,在这30s的等待时间里,有人进来了,30s就重新从0开始计时,然后又有人进来了,30s就又重新计时,直到等待时间30s超时才会关门上升。
实现防抖
以上面的代码为例子来说明如何实现防抖:一直滚动鼠标,第一次触发
scroll事件,在事件的执行函数里创建一个定时器,在指定的时间间隔后才运行相关代码。然后第二次触发scroll事件,如果此时前面设置的定时器还没开始执行,就清除前一次的定时器并重新设置一个。这么做的目的就是让scroll事件的执行函数在事件停止触发一段时间后才去执行,以此实现防抖。function debounce(func, delay) {
let timeout; return function(){
// context 是为了绑定 this
let context = this;
// args 是为了能正常使用事件对象 event
let args = arguments; if (timeout) clearTimeout(timeout);
timeout = setTimeout(()=> {
func.apply(context, args);
}, delay);
}
} window.addEventListener('scroll', debounce(incNum, 1000), false);
从下面图片可以看出,防抖处理后,只有在鼠标停止滚动一段时间后,才会输出
num和秒数。
取消执行
当滚动鼠标后,在1s的等待时间里,突然想取消运行
scroll事件的函数了,该怎么办呢?答案是:在定时器没运行前,清除定时器。
function debounce(func, delay) {
let timeout; let debounced = function(){
let context = this;
let args = arguments; if (timeout) clearTimeout(timeout);
timeout = setTimeout(()=> {
func.apply(context, args);
}, delay);
} // 取消将要执行的定时器
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
console.log('已取消');
} return debounced;
} let testFunc = debounce(incNum, 1000);
window.addEventListener('scroll', testFunc, false);
// 在页面的按钮上绑定取消函数
document.getElementById('cancel').addEventListener('click', testFunc.cancel, false);
立即执行
只要触发
scroll事件,函数就立即执行,但必须要在函数执行完毕并过了一段时间后,再次滚动鼠标才会再次执行函数,而在等待时间里,如果滚动鼠标,等待时间会重新计时。function debounce(func, delay, immediate) {
let timeout; let debounced = function(){
let context = this;
let args = arguments; if (timeout) clearTimeout(timeout);
// immediate 为 true 就表示立即执行,忽略或者为 false 即非立即执行
if (immediate) {
let callNow = !timeout;
timeout = setTimeout(()=> {
timeout = null;
}, delay);
if (callNow) func.apply(context, args);
} else {
timeout = setTimeout(()=> {
func.apply(context, args);
}, delay);
}
} // 取消将要执行的定时器
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
console.log('已取消');
} return debounced;
} window.addEventListener('scroll', debounce(incNum, 1000, true), false);
节流(throttle)
什么是节流?
还是电梯的例子:一部电梯开门等待30s就会关门上升,在这30s的等待时间里,有人进来了,计时继续累计,然后又有人进来了,计时依然累计,然后30s计时到了就立即关门上升(我还没上车呢.jpg)。
简单来说,就是连续触发事件,但在固定时间内只执行一次函数。
定时器实现
// 定时器版本,鼠标滚动1s后才执行函数
function throttle(func, delay){
let timeout;
return function(){
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(()=> {
func.apply(context, args);
}, delay);
}
}
} window.addEventListener('scroll', throttle(incNum, 1000), false);
疯狂滚动鼠标,但从下图可以看出函数只每秒执行一次。

时间戳实现
// 时间戳版本,鼠标滚动函数立即执行,间隔1s再执行下一次
function throttle(func, delay) {
let previous = 0; return function() {
let now = Date.now();
let args = arguments;
if ( (now - previous) >= delay ) {
func.apply(this, args);
previous = now;
}
}
} window.addEventListener('scroll', throttle(incNum, 1000), false);
合并实现与取消
将定时器和时间戳两个版本合并在一起,可以实现滚动鼠标,函数就立即执行,间隔1s再执行下一次,然后停止滚动鼠标后,还会多执行一次的效果。
function throttle(func, delay) {
let previous = 0;
let timeout;
let now; let throttled = function() {
now = Date.now();
let context = this;
let args = arguments;
if ( (now - previous) >= delay ) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(()=> {
previous = now;
timeout = null;
func.apply(context, args);
}, delay - (now - previous));
}
} // 取消函数
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
} return throttled;
} let testFunc = throttle(incNum, 1000);
window.addEventListener('scroll', testFunc, false);
// 在页面的按钮上绑定取消函数
document.getElementById('cancel').addEventListener('click', testFunc.cancel, false);
JS: 防抖节流的更多相关文章
- js 防抖 节流 JavaScript
实际工作中,通过监听某些事件,如scroll事件检测滚动位置,根据滚动位置显示返回顶部按钮:如resize事件,对某些自适应页面调整DOM的渲染:如keyup事件,监听文字输入并调用接口进行模糊匹配等 ...
- js 防抖 节流
函数防抖:将几次操作合并为一此操作进行.原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置.这样一来,只有最后一次操作能被触发.( ...
- js防抖节流
防抖(debounce) 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间. 防抖函数分为非立即执行版和立即执行版. 非立即执行版: 第一 ...
- 深入理解JS防抖与节流
参考博客:JS防抖和节流,感谢作者的用心分享 日常开发过程中,滚动事件做复杂计算频繁调用回调函数很可能会造成页面的卡顿,这时候我们更希望把多次计算合并成一次,只操作一个精确点,JS把这种方式称为deb ...
- js 函数节流和防抖
js 函数节流和防抖 throttle 节流 事件触发到结束后只执行一次. 应用场景 触发mousemove事件的时候, 如鼠标移动. 触发keyup事件的情况, 如搜索. 触发scroll事件的时候 ...
- js防抖和节流优化浏览器滚动条滚动到最下面时加载更多数据
防抖和节流,主要是用来防止过于平凡的执行某个操作,如浏览器窗口变化执行某个操作,监听某个input输入框keyup变化,瀑布流布局时Y轴滚动,图片加载. js函数的防抖 经过一段事件才执行某个操作,如 ...
- 因为它,我差点删库跑路:js防抖与节流
前言 前端踩雷:短时间内重复提交导致数据重复. 对于前端大佬来说,防抖和节流的技术应用都是基本操作.对于"兼职"前端开发的来说,这些都是需要躺平的坑. 我们今天就来盘一盘js防抖与 ...
- 面试必问题:JS防抖与节流
摘要:防抖与节流可谓是面试常见,其实很好理解,下面带你分分钟了解防抖与节流的基本思想与写法~ 本文分享自华为云社区<JS防抖与节流快速了解与应用>,作者:北极光之夜. . 一.速识防抖: ...
- vue防抖节流之v-debounce--throttle使用指南
最新封装了一个vue防抖节流自定义指令,发布到npm上,有用欢迎star,谢谢! npm地址:https://www.npmjs.com/package/v-debounce-throttle git ...
随机推荐
- pthread_once 和 pthread_key
http://blog.csdn.net/rickyguo/article/details/6259410 一次性初始化 有时候我们需要对一些posix变量只进行一次初始化,如线程键(我下面会讲到). ...
- 2018.09.15 poj1734Sightseeing trip(floyd求最小环)
跟hdu1599差不多.. 只是需要输出方案. 这个可以递归求解. 代码: #include<iostream> #include<cstdio> #include<cs ...
- org.hibernate.HibernateException: /hibernate.cfg.xml not found等三个问题
初次配置hibernate在myeclipse上: 出现三个问题,怎么都不好使,比对代码,没有问题,查看路径还是没有问题: 1.org.hibernate.HibernateException: /h ...
- POP介绍与使用实践(快速上手动画)[转]
前言 动画在APP开发过程中 大家多多少少都会接触到 而且随着ios7的扁平化风格启用之后 越来越多的APP开始尝试加入各种绚丽的动画交互效果以增加APP的用户体验(当然 还是以国外的APP居多) 有 ...
- Js中 关于top、clientTop、scrollTop、offsetTop
网页可见区域宽: document.body.clientWidth; 网页可见区域高: document.body.clientHeight; 网页可见区域宽: document.body.offs ...
- (最小生成树)Truck History --POJ -- 1789
链接: http://poj.org/problem?id=1789 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 2213 ...
- MFC 怎样获得某个窗口的句柄?
GetSafeHandle();this-> hWnd;GetDlgItem(hwnd,ID);//获取窗口ID所对应的HWND的子窗口句柄 在主窗口中,如果要用到父窗口的句柄,可以用 HWND ...
- Qt .pro文件 详解
1. TEMPLATE变量TEMPLATE描述了为建立目标文件而采用何种模板,即生成何种形式的Makefile文件.Qmake工具定义了5种模板:1. 应用程序App,为建立一个Qt应用程序创建Mak ...
- HDU1078 FatMouse and Cheese(DFS+DP) 2016-07-24 14:05 70人阅读 评论(0) 收藏
FatMouse and Cheese Problem Description FatMouse has stored some cheese in a city. The city can be c ...
- android build.gradle(groovy)
一.build.Gradle 这个 build.Gradle 文件来自 drakeet 大神的 Meizi 项目我直接在代码上加注释,参照着注释看代码就行,是不是发现有很多代码平时都没看见过. //M ...