浅谈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 相关文章推荐
json简单介绍
Jun 10 Javascript
javascript 写类方式之一
Jul 05 Javascript
jquery.validate使用攻略 第二部
Jul 01 Javascript
javascript Array.prototype.slice使用说明
Oct 11 Javascript
Notify - 基于jquery的消息通知插件
Oct 18 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
May 14 Javascript
IE6 hack for js 集锦
Sep 23 Javascript
60行js代码实现俄罗斯方块
Mar 31 Javascript
JSONP原理及简单实现
Jun 08 Javascript
Koa项目搭建过程详细记录
Apr 12 Javascript
vue-cli 构建骨架屏的方法示例
Nov 08 Javascript
原生js实现瀑布流效果
Mar 09 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用正则表达式匹配中文实例详解
2013/11/06 PHP
WordPress中查询文章的循环Loop结构及用法分析
2015/12/17 PHP
PHP设计模式之模板方法模式实例浅析
2018/12/20 PHP
Extjs在exlipse中设置自动提示的方法
2010/04/07 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
2013/10/24 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
js加减乘除丢失精度问题解决方法
2014/05/16 Javascript
nodejs 的 session 简单使用
2016/06/06 NodeJs
jQuery文件上传控件 Uploadify 详解
2016/06/20 Javascript
jstl中判断list中是否包含某个值的简单方法
2016/10/14 Javascript
基于ajax与msmq技术的消息推送功能实现代码
2016/12/26 Javascript
JQuery 获取Dom元素的实例讲解
2017/07/08 jQuery
微信小程序之页面跳转和参数传递的实现
2017/09/29 Javascript
深入解析koa之中间件流程控制
2019/06/17 Javascript
Python threading多线程编程实例
2014/09/18 Python
python+django快速实现文件上传
2016/10/24 Python
Python中用psycopg2模块操作PostgreSQL方法
2017/11/28 Python
Python完成毫秒级抢淘宝大单功能
2019/06/06 Python
Python 线程池用法简单示例
2019/10/02 Python
使用Python进行中文繁简转换的实现代码
2019/10/18 Python
PyTorch 中的傅里叶卷积实现示例
2020/12/11 Python
Canvas引入跨域的图片导致toDataURL()报错的问题的解决
2018/09/19 HTML / CSS
StubHub哥伦比亚:购买和出售您的门票
2016/10/20 全球购物
澳大利亚在线购买儿童玩具:Toy Universe
2017/12/28 全球购物
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
公务员培训心得体会
2013/12/28 职场文书
年度考核评语
2014/01/19 职场文书
酒店采购员岗位职责
2014/03/14 职场文书
教师职业道德事迹材料
2014/08/18 职场文书
小学生十佳少年事迹材料
2014/08/20 职场文书
单位一把手群众路线四风问题整改措施
2014/09/25 职场文书
成绩单家长意见
2015/06/03 职场文书
雷锋的观后感
2015/06/10 职场文书
2015国庆节感想
2015/08/04 职场文书
Python import模块的缓存问题解决方案
2021/06/02 Python