防抖与节流

事件节流,函数防抖

防抖(Debouncing)

概念:防抖技术是指在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。防抖确保了一个事件处理函数在一定时间内只执行一次。

作用:防抖常用于输入框搜索、窗口大小调整、滚动事件等场景,这些场景下事件可能会非常频繁地触发,但并不需要每次触发都执行相应的处理函数。防抖可以减少不必要的计算或DOM操作,提高性能。

使用场景:

搜索框实时搜索建议(用户停止输入后才开始搜索)
窗口大小调整时重新布局(窗口大小调整停止后才开始重新布局)
滚动事件监听(滚动停止后执行某些操作)

/*
*  
 * 事件节流函数  
 *  
 * 该函数用于限制函数的执行频率,确保函数在指定的时间间隔内最多执行一次。  
 * 这在处理如滚动、窗口大小调整等高频事件时非常有用,以避免性能问题。  
 *  
 * @param {Function} func - 需要进行节流的函数。  
 * @param {number} delay - 节流的时间间隔,以毫秒为单位。  
 * @returns {Function} - 返回一个新的函数,这个新函数是func的节流版本。  
 */  
function tool_throttle(func, delay) {  
    var timer = null; // 用于存储setTimeout的定时器ID,以便在需要时清除它。  
    var startTime = Date.parse(new Date()); // 记录上一次执行func的时间戳(但这里的实现方式并不完全准确,因为它只记录了一次开始时间)。  
  
    // 返回一个新的函数,这个函数将作为func的节流版本被调用。  
    return function() {  
        var curTime = Date.parse(new Date()); // 获取当前时间戳。  
        // 计算距离上次执行func还有多少时间。  
        // 但注意,这里的实现方式有误,因为它没有正确反映func实际执行的时间间隔。  
        // 更准确的方式是记录上一次执行func后的时间戳,而不是只记录一个开始时间。  
        var remaining = delay - (curTime - startTime);  
        var context = this; // 保存调用上下文,以便func能够以正确的this值执行。  
        var args = arguments; // 保存调用参数,以便func能够接收到正确的参数。  
  
        // 清除之前的定时器(如果存在),以避免重复执行。  
        clearTimeout(timer);  
  
        // 如果剩余时间小于等于0,说明已经到了执行func的时间,或者已经超过了设定的时间间隔。  
        if (remaining <= 0) {  
            func.apply(context, args); // 执行func,并传入正确的上下文和参数。  
            // 更新startTime为当前时间戳(但这里并不准确,因为理想情况下应该记录func执行完成后的时间)。  
            startTime = Date.parse(new Date());  
        } else {  
            // 如果还没到执行func的时间,则设置一个定时器,在剩余时间后执行func。  
            timer = setTimeout(function() {  
                func.apply(context, args);  
            }, remaining);  
            // 注意:这里的setTimeout实际上并不会精确地在remaining毫秒后执行,  
            // 因为JavaScript的事件循环和定时器解析可能会有一定的延迟。  
        }  
    };  
}  
  
// 注意:上述实现虽然可以工作,但关于startTime的处理并不完全符合节流函数的典型实现。  
// 更常见的做法是在每次执行func后更新一个“上次执行时间”的变量,而不是仅记录一个开始时间。


节流(Throttling)

概念:节流技术是指在规定时间内,只执行一次函数。如果这个单位时间内触发多次函数,只有一次能生效。节流通过减少函数的执行次数来达到性能优化的目的。

作用:节流常用于控制一些频繁执行但不需要每次都响应的事件,如滚动事件、鼠标移动事件等。通过节流,可以控制这些事件的处理函数在固定时间间隔内只执行一次,从而避免因为过于频繁的执行而导致的性能问题。

使用场景:

滚动加载(滚动时不是每次滚动都加载,而是在滚动停止一段时间后加载)
游戏中的射击(控制射击频率,避免因为快速点击而导致的性能问题)
实时数据监控(如实时日志监控,不需要每秒都刷新数据,可以设定每5秒刷新一次)

/**  
 * 函数防抖(Debounce)  
 *  
 * 该函数用于限制回调函数的执行频率,确保回调函数在事件被触发n秒后再执行,  
 * 如果在这n秒内又被触发,则重新计时。这常用于处理如窗口大小调整、输入框内容校验等事件。  
 *  
 * @param {Function} fn - 需要进行防抖处理的回调函数。  
 * @param {number} delay - 延迟时间,单位毫秒,表示回调函数被触发后需要等待的时间。  
 * @returns {Function} - 返回一个新的函数,这个新函数是fn的防抖版本。  
 */  
function tool_debounce(fn, delay) {  
    // 维护一个定时器变量,用于存储setTimeout返回的ID,以便在需要时能够清除它。  
    let timer = null;  
  
    // 返回一个新的函数,这个新函数将作为fn的防抖版本被调用。  
    return function() {  
        // 通过 ‘this’ 和 ‘arguments’ 获取原始函数被调用时的上下文和参数。  
        // 这样做是为了确保防抖函数执行时,能够以正确的上下文和参数调用原始函数。  
        let context = this; // 保存调用上下文  
        let args = arguments; // 保存调用参数  
  
        // 如果已经存在定时器,则清除它,这样可以确保如果事件在短时间内被连续触发,  
        // 那么之前的等待将被取消,重新开始计时。  
        clearTimeout(timer);  
  
        // 设置一个新的定时器,在指定的延迟时间后执行原始函数。  
        timer = setTimeout(function() {  
            // 使用apply方法来调用原始函数,确保能够正确地传入上下文和参数。  
            fn.apply(context, args);  
        }, delay);  
    };  
}  
  
// 使用示例:  
// 假设有一个需要防抖处理的函数updatePosition,它根据鼠标位置更新页面元素的位置。  
// function updatePosition(x, y) {  
//     console.log(`Mouse position updated to (${x}, ${y})`);  
// }  
  
// 使用tool_debounce函数创建updatePosition的防抖版本。  
// const debouncedUpdatePosition = tool_debounce(updatePosition, 250);  
  
// 现在,你可以将debouncedUpdatePosition绑定到如mousemove事件上,  
// 它将确保updatePosition函数在鼠标停止移动后250毫秒内只被调用一次。

总结

  • 防抖:确保函数在事件停止触发一定时间后才执行,减少不必要的执行次数。
  • 节流:在固定时间间隔内只执行一次函数,控制函数的执行频率。

选择使用防抖还是节流,主要取决于具体的应用场景和需求。防抖更适用于那些需要等待用户操作停止后再执行的任务,如搜索建议、窗口大小调整等;而节流则更适用于那些需要控制执行频率,但又不希望完全停止执行的任务,如滚动加载、游戏射击等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万水千山走遍TML

您的鼓励,将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值