浅谈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 对象模型 执行模型
Dec 06 Javascript
JavaScript DOM 编程艺术(第2版)读书笔记(JavaScript的最佳实践)
Oct 01 Javascript
浅析hasOwnProperty方法的应用
Nov 20 Javascript
javascript 通用loading动画效果实例代码
Jan 14 Javascript
Jquery 点击按钮自动高亮实现原理及代码
Apr 25 Javascript
完美实现js焦点轮播效果(二)(图片可滚动)
Mar 07 Javascript
react 创建单例组件的方法
Apr 26 Javascript
原生js实现移动端Touch轮播图的方法步骤
Jan 03 Javascript
JS学习笔记之贪吃蛇小游戏demo实例详解
May 29 Javascript
Nuxt使用Vuex的方法示例
Sep 06 Javascript
vue等两个接口都返回结果再执行下一步的实例
Sep 08 Javascript
详解Node.js如何处理ES6模块
May 15 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小教程之实现双向链表
2014/06/12 PHP
Ubuntu彻底删除PHP7.0的方法
2018/07/27 PHP
jQuery插件实现屏蔽单个元素使用户无法点击
2013/04/12 Javascript
Js与Jq 获取页面元素值的方法和差异对比
2015/04/30 Javascript
javascript中 try catch用法
2015/08/16 Javascript
Javascript验证方法大全
2015/09/21 Javascript
jquery获取文档高度和窗口高度汇总
2016/01/25 Javascript
原生JavaScript编写canvas版的连连看游戏
2016/05/29 Javascript
jQuery 获取select选中值及清除选中状态
2016/12/13 Javascript
Mongoose学习全面理解(推荐)
2017/01/21 Javascript
你真的了解BOM中的history对象吗
2017/02/13 Javascript
自定义vue全局组件use使用、vuex的使用详解
2017/06/14 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
axios对请求各种异常情况处理的封装方法
2018/09/25 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
2019/07/03 Javascript
微信小程序中为什么使用var that=this
2019/08/27 Javascript
关于layui导航栏不展示下拉列表的解决方法
2019/09/25 Javascript
Layui 解决表格异步调用后台分页的问题
2019/10/26 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
jquery添加div实现消息聊天框
2020/02/08 jQuery
vue学习笔记之Vue中css动画原理简单示例
2020/02/29 Javascript
Javascript call及apply应用场景及实例
2020/08/26 Javascript
一篇文章看懂JavaScript中的回调
2021/01/05 Javascript
python机器学习之决策树分类详解
2017/12/20 Python
在python image 中安装中文字体的实现方法
2019/08/22 Python
python 实现按对象传值
2019/12/26 Python
python虚拟环境模块venv使用及示例
2020/03/04 Python
MyFrenchPharma中文网:最大的法国药妆平台
2016/10/07 全球购物
Lookfantastic澳大利亚官网:英国知名美妆购物网站
2021/01/07 全球购物
Lucene推荐的分页方式是什么?
2015/12/07 面试题
外企办公室竞聘演讲稿
2013/12/29 职场文书
应聘文员自荐信范文
2014/03/11 职场文书
总结表彰大会主持词
2014/03/26 职场文书
关爱留守儿童倡议书
2014/04/15 职场文书
求职简历自荐信怎么写
2015/03/26 职场文书
2015迎新晚会开场白
2015/05/29 职场文书