浅谈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 相关文章推荐
用htc组件制作windows选项卡
Jan 13 Javascript
jquery remove方法应用详解
Nov 22 Javascript
JavaScript 语言基础知识点总结(思维导图)
Nov 10 Javascript
JS判断键盘是否按的回车键并触发指定按钮点击操作的方法
Feb 13 Javascript
JavaScript函数参数的传递方式详解
Mar 06 Javascript
Angular.js实现动态加载组件详解
May 28 Javascript
Vue工程模板文件 webpack打包配置方法
Dec 26 Javascript
详解如何在react中搭建d3力导向图
Jan 12 Javascript
原生JS实现的双色球功能示例
Feb 02 Javascript
vue中vee validate表单校验的几种基本使用
Jun 25 Javascript
详解VUE项目中安装和使用vant组件
Apr 28 Javascript
对vuex中store和$store的区别说明
Jul 24 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
PHP中的超全局变量
2006/10/09 PHP
PHP原生函数一定好吗?
2014/12/08 PHP
PHP通过反射动态加载第三方类和获得类源码的实例
2015/11/27 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
PHP html_entity_decode()函数讲解
2019/02/25 PHP
jQuery初学:find()方法及children方法的区别分析
2011/01/31 Javascript
深入理解javascript中return的作用
2013/12/30 Javascript
JavaScript字符串常用类使用方法汇总
2015/04/14 Javascript
JavaScript实现鼠标点击后层展开效果的方法
2015/05/13 Javascript
微信小程序  TLS 版本必须大于等于1.2问题解决
2017/02/22 Javascript
JS实现的添加弹出层并完成锁屏操作示例
2017/04/07 Javascript
React根据宽度自适应高度的示例代码
2017/10/11 Javascript
Parcel.js + Vue 2.x 极速零配置打包体验教程
2017/12/24 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
jQuery实现基本淡入淡出效果的方法详解
2018/09/05 jQuery
TypeScript基础入门教程之三重斜线指令详解
2018/10/22 Javascript
浅谈vue websocket nodeJS 进行实时通信踩到的坑
2020/09/22 NodeJs
vue项目打包后请求地址错误/打包后跨域操作
2020/11/04 Javascript
vue二选一tab栏切换新做法实现
2021/01/19 Vue.js
python实现员工管理系统
2018/01/11 Python
使用python实现链表操作
2018/01/26 Python
PyQT实现多窗口切换
2018/04/20 Python
pyqt5的QComboBox 使用模板的具体方法
2018/09/06 Python
Python进阶之全面解读高级特性之切片
2019/02/19 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
Python使用QQ邮箱发送邮件实例与QQ邮箱设置详解
2020/02/18 Python
Python Selenium 设置元素等待的三种方式
2020/03/18 Python
python编程的核心知识点总结
2021/02/08 Python
英国领先的电视购物零售商:Ideal World
2019/03/18 全球购物
Bose加拿大官方网站:美国知名音响品牌
2019/03/21 全球购物
大学生党员自我批评
2014/02/14 职场文书
感恩节活动策划方案
2014/05/16 职场文书
优秀毕业生就业推荐信
2014/05/22 职场文书
简单通用的简历自我评价
2014/09/21 职场文书
幼儿园大班见习报告
2014/10/31 职场文书
2015应届毕业生求职信范文
2015/03/20 职场文书