博客
关于我
JS魔法堂:函数节流(throttle)与函数去抖(debounce)
阅读量:429 次
发布时间:2019-03-06

本文共 3060 字,大约阅读时间需要 10 分钟。

debounce与throttle:JavaScript事件防抖动的两种解决方案


前言

在实际开发中,频繁触发DOM操作或资源加载可能导致UI卡顿甚至浏览器崩溃。以下场景经常引发问题:

  • window对象的resize、scroll事件
  • 拖拽时的mousemove事件
  • 射击游戏中的mousedown、keydown事件
  • 文字输入、自动完成的keyup事件
  • 针对这些事件,有两种常见的解决方案:debouncethrottle


    debounce:防抖动机制的定义

    debounce 的核心思想是:在指定的空闲时间内,多次触发同一事件只执行一次。类似于弹簧的状态,只有在手松开后才会恢复原状。

    简单实现:

    var debounce = function(idle, action) {    var last = null;    return function() {        var ctx = this;        var args = arguments;        clearTimeout(last);        last = setTimeout(function() {            action.apply(ctx, args);        }, idle);    };};

    throttle:速率限制机制的定义

    throttle 的目标是限制事件处理的执行频率。每隔指定时间执行一次相关操作,类似于水流的滴落。

    简单实现:

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

    Underscore v1.7.0的实现剖析

    _.throttle函数

    _.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;        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;    };};

    精彩之处

    • remaining <= 0 用于检测是否满足空闲时间。
    • remaining > wait 用于处理时间异常(如系统时间修改)。

    _.debounce函数

    _.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;    };};

    精彩之处

    • 递归调用 setTimeout 来确保在空闲时间内只执行一次函数。
    • immediate 参数控制是否在首次调用时立即执行函数。

    总结

    debouncethrottle 都通过减少事件处理的执行频率来提升性能,但核心机制有明显差异:

    • debounce 更关注空闲时间,适用于需要延迟处理的场景。
    • throttle 则强调执行频率,适用于需要稳定化处理的场景。

    选择时需结合具体需求,结合各JS库的实现进行深入理解。


    参考

    你可能感兴趣的文章
    Oracle EBS OPM 发放生产批
    查看>>
    Oracle EBS-SQL (BOM-15):检查多层BOM(含common BOM).sql
    查看>>
    Oracle EBS环境下查找数据源(OAF篇)
    查看>>
    oracle Extract 函数
    查看>>
    uni-app开发环境自动部署的一个误区(App running at...)
    查看>>
    Oracle GoldenGate Director安装和配置(无图)
    查看>>
    oracle instr函数详解
    查看>>
    Oracle Java所有版本的下载链接
    查看>>
    oracle ogg 单实例双向复制搭建(oracle-oracle)--Oracle GoldenGate
    查看>>
    oracle ORA-14402 OGG-01296
    查看>>
    oracle partition by list,深入解析partition-list 分区
    查看>>
    Oracle PL/SQL Dev工具(破解版)被植入勒索病毒的安全预警及自查通告
    查看>>
    oracle rac集群的东西之QQ聊天
    查看>>
    Oracle Schema Objects——Tables——Table Compression
    查看>>
    oracle scott趣事
    查看>>
    oracle script
    查看>>
    Oracle select表要带双引号的原因
    查看>>
    Oracle SOA Suit Adapter
    查看>>
    Oracle Spatial GeoRaster 金字塔栅格存储
    查看>>
    Oracle spatial 周边查询SQL
    查看>>