浅谈JS函数节流防抖


Posted in Javascript onOctober 18, 2017

在前端开发中有一部分的用户行为会频繁的触发事件执行,而对于DOM操作、资源加载等耗费性能的处理,很可能导致界面卡顿,甚至浏览器的崩溃。函数节流(throttle)和函数防抖(debounce)就是为了解决类似需求应运而生的。

函数节流(throttle)

函数节流就是预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。好像水滴攒到一定重量才会落下一样。

场景:

  • 窗口调整(resize)
  • 页面滚动(scroll)
  • 抢购疯狂点击(mousedown)

实现:

function throttle(method, delay){
  var last = 0;
  return function (){
    var now = +new Date();
    if(now - last > delay){
      method.apply(this,arguments);
      last = now;
    }
  }
}

document.getElementById('throttle').onclick = throttle(function(){console.log('click')},2000);

underscore实现:

_.throttle = function(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : _.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function() {
    var now = _.now();
    if (!previous && options.leading === false) previous = now;
    //计算剩余时间
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    //剩余时间小于等于0或者剩余时间大于等待时间(本地时间变动出现)
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
};

函数防抖(debounce)

函数防抖就是在函数需要频繁触发情况时,只有足够空闲的时间,才执行一次。好像公交司机会等人都上车后才出站一样。

场景:

  • 实时搜索(keyup)
  • 拖拽(mousemove)

实现:

function debounce(method, delay){
  var timer = null;
  return function(){
    var context = this,args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function(){
      method.apply(context, args);
    },delay);
  }
}

document.getElementById('debounce').onclick = debounce(function(){console.log('click')},2000);

underscore实现:

_.debounce = function(func, wait, immediate) {
  var timeout, args, context, timestamp, result;
  var later = function() {
    var last = _.now() - timestamp;
    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };
  return function() {
    context = this;
    args = arguments;
    timestamp = _.now();
    var callNow = immediate && !timeout;
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }
    return result;
  };
};

函数节流(throttle)和函数防抖(debounce)都是通过延时逻辑操作来提升性能的方法,在前端优化中是常见且重要的解决方式。可以从概念和实际应用中理解两者的区别,在需要的时候选择合适的方法处理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 乱码问题
Aug 06 Javascript
javascript中的107个基础知识收集整理 推荐
Mar 29 Javascript
JS判断当前日期是否大于某个日期的实现代码
Sep 02 Javascript
jQuery实现响应浏览器缩放大小并改变背景颜色
Oct 31 Javascript
jQuery实现textarea自动增长宽高的方法
Dec 18 Javascript
详解react、redux、react-redux之间的关系
Apr 11 Javascript
Vue的transition-group与Virtual Dom Diff算法的使用
Dec 09 Javascript
Angular+Ionic使用queryParams实现跳转页传值的方法
Sep 05 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
Sep 10 Javascript
JS实现放大镜效果
Sep 21 Javascript
JavaScript中layim之整合右键菜单的示例代码
Feb 06 Javascript
JavaScript前端面试组合函数
Jun 21 Javascript
用vue封装插件并发布到npm的方法步骤
Oct 18 #Javascript
详解Js中的模块化是如何实现的
Oct 18 #Javascript
JS跳转手机站url的若干注意事项
Oct 18 #Javascript
vue实现手机号码抽奖上下滚动动画示例
Oct 18 #Javascript
Angular.js实现获取验证码倒计时60秒按钮的简单方法
Oct 18 #Javascript
浅谈Node异步编程的机制
Oct 18 #Javascript
js实现随机点名系统(实例讲解)
Oct 18 #Javascript
You might like
PHP4.04简明安装
2006/10/09 PHP
页面乱码问题的根源及其分析
2013/08/09 PHP
PHP中定义数组常量(array常量)的方法
2014/11/17 PHP
简单的php+mysql聊天室实现方法(附源码)
2016/01/05 PHP
PHPWind9.0手动屏蔽验证码解决后台关闭验证码但是依然显示的问题
2016/08/12 PHP
/etc/php-fpm.d/www.conf 配置注意事项
2017/02/04 PHP
Swoole源码中如何查询Websocket的连接问题详解
2020/08/30 PHP
百度移动版的url编码解码示例
2014/04/29 Javascript
js实现网页自动刷新可制作节日倒计时效果
2014/05/27 Javascript
百度地图api如何使用
2015/08/03 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
Node.js 日志处理模块log4js
2016/08/28 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
2016/12/24 Javascript
Angular4实现鼠标悬停3d倾斜效果
2017/10/25 Javascript
微信小程序实现带缩略图轮播效果
2018/11/04 Javascript
微信小程序如何实现点击图片放大功能
2020/01/21 Javascript
记录一次websocket封装的过程
2020/11/23 Javascript
用Python实现通过哈希算法检测图片重复的教程
2015/04/02 Python
python并发编程之多进程、多线程、异步和协程详解
2016/10/28 Python
PyCharm配置mongo插件的方法
2018/11/30 Python
Python实现基于SVM的分类器的方法
2019/07/19 Python
Python的Tkinter点击按钮触发事件的例子
2019/07/19 Python
pytorch 固定部分参数训练的方法
2019/08/17 Python
Tensorflow 实现释放内存
2020/02/03 Python
JNI的定义
2012/11/25 面试题
你所在的项目是如何确定版本号的
2015/12/28 面试题
教师应聘个人求职信
2013/12/10 职场文书
实习生自我评价
2014/01/18 职场文书
《圆明园的毁灭》教学反思
2014/02/28 职场文书
党的群众路线对照检查材料
2014/08/27 职场文书
中秋节国旗下演讲稿
2014/09/05 职场文书
擅自离岗检讨书
2014/09/12 职场文书
机关领导干部作风整顿整改措施
2014/09/19 职场文书
公司放假通知范文
2015/04/14 职场文书
JavaScript 实现页面滚动动画
2021/04/24 Javascript
Python 键盘事件详解
2021/11/11 Python