浅谈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让setInteval里的函数参数中的this指向特定的对象
Jan 31 Javascript
jQuery学习笔记 更改jQuery对象
Sep 19 Javascript
extjs render 用法介绍
Sep 11 Javascript
使用JavaScript实现弹出层效果的简单实例
May 31 Javascript
JS JSOP跨域请求实例详解
Jul 04 Javascript
Bootstrap表格使用方法详解
Feb 17 Javascript
AngularJS 验证码60秒倒计时功能的实现
Jun 05 Javascript
jQuery Datatable 多个查询条件自定义提交事件(推荐)
Aug 24 jQuery
Vue+axios实现统一接口管理的方法
Jul 23 Javascript
vue.js配合$.post从后台获取数据简单demo分享
Aug 11 Javascript
javaScript把其它类型转换为Number类型
Oct 13 Javascript
Angular利用HTTP POST下载流文件的步骤记录
Jul 26 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下保存远程图片到本地的办法
2010/08/08 PHP
rephactor 优秀的PHP的重构工具
2011/06/09 PHP
PHP分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
javascript 图片上传预览-兼容标准
2009/06/01 Javascript
防止页面被iframe(兼容IE,Firefox火狐)
2010/07/04 Javascript
JavaScript中使用ActiveXObject操作本地文件夹的方法
2014/03/28 Javascript
基于javascript的JSON格式页面展示美化方法
2014/07/02 Javascript
javascript基本包装类型介绍
2015/04/10 Javascript
JavaScript中的getDay()方法使用详解
2015/06/09 Javascript
JS中产生标识符方式的演变
2015/06/12 Javascript
详解javascript中的事件处理
2015/11/06 Javascript
使用Node.js处理前端代码文件的编码问题
2016/02/16 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
基于jQuery实现顶部导航栏功能
2016/12/27 Javascript
js 简易版滚动条实例(适用于移动端H5开发)
2017/06/26 Javascript
import与export在node.js中的使用详解
2017/09/28 Javascript
详解nodeJs文件系统(fs)与流(stream)
2018/01/24 NodeJs
python基础教程之循环介绍
2014/08/29 Python
Python装饰器decorator用法实例
2014/11/10 Python
python定时检查某个进程是否已经关闭的方法
2015/05/20 Python
Python实现周期性抓取网页内容的方法
2015/11/04 Python
python 字符串常用方法汇总详解
2019/09/16 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
Django实现列表页商品数据返回教程
2020/04/03 Python
Python学习之路之pycharm的第一个项目搭建过程
2020/06/18 Python
Python爬虫爬取微信朋友圈
2020/08/06 Python
Python如何使用ConfigParser读取配置文件
2020/11/12 Python
仿酷狗html5手机音乐播放器主要部分代码
2013/05/15 HTML / CSS
豪华床上用品 :Jennifer Adams
2019/09/15 全球购物
一个J2EE项目团队的主要人员组成是什么
2012/06/04 面试题
汽车专业求职信
2014/06/05 职场文书
党风廉正建设责任书
2015/01/29 职场文书
杜甫草堂导游词
2015/02/03 职场文书
新兵入伍决心书
2015/09/22 职场文书
如何用python插入独创性声明
2021/03/31 Python
根德5570型九灯四波段立体声收音机是电子管收音机的楷模 ? 再论5570
2022/04/05 无线电