前言

有一些浏览器事件可以在很短的事件内快速触发多次,例如 调整窗口大小向下滚动 页面。例如,如果将事件监听器绑定到窗口滚动事件上,并且用户继续非常快速地向下滚动页面,你的事件可能会在3秒的范围内被触发数千次。这可能会导致一些严重的性能问题,

如果在面试中讨论构建应用程序和事件,如滚动、窗口调整大小,或键盘按下的事件时,一定要提及函数防抖动和函数节流来提升页面速度和性能。

直接绑定函数到scroll事件是非常错误的决定,当用户滚动页面时,页面可能会变得非常慢甚至未响应。而函数防抖和函数节流是解决这个问题的一种方式,通过限制需要经过的事件,直至再次调用函数,在处理一些高频率触发的 DOM 事件的时候,它们都能极大提高用户体验。

函数防抖

如果一个事件被频繁触发多次,并且触发的时间间隔过短,则防抖函数可以使得对应的事件处理函数只执行一次

// debounce函数用来包裹我们的事件处理方法
function debounce(fn, delay){
    // 持久化一个定时器
    let timer = null
    
    // 闭包函数可以访问timer
    return function(){
        // 通过 this 和 arguments 获得函数的作用域和参数
        let context = this
        let args = arguments
        // 如果事件被触发,清除timer并重新开始计时
        clearTimeout(timer)
        timer = setTimeout(function() {
            fn.apply(context, args)
        }, delay)
    }
}

function foo(){
    console.log('You are scrolling!')
}

document.addEventListener('scroll', debounce(foo, 50));

函数节流

throttle 的概念理解稍微容易一些,如果一个事件被频繁触发多次,节流函数可以按照固定频率去执行对应的事件处理方法

function throttle(fn, threshold){
    var last
    
    var timer
    
    threshold || (threshold = 250)
    
    return function(){
        let context = this
        let args = arguments
        
        var now = +new Date()
        
        if(last&&now<last+threshold){
            clearTimeout(timer)
            
            timer = setTimeout(function(){
                last = now
                fn.apply(context, args)
            },threshold)
        }else {
            last = now
            fn.apply(context, args)
        }
    }
}

你可能感兴趣的文章

ramark · 2017年12月14日

var test1 = throttle(function(){

console.log("log1",+new Date())

},300)
var test2 = _.throttle(function(){

console.log("log2",+new Date())

},300)
setInterval(function(){

test1();
test2();

},100)
以上代码,test1使用lz的throttle,test2使用lodash的throttle,log1间隔400ms,log2间隔300ms

回复

载入中...
jhhfft jhhfft

398 声望

发布于专栏

每日技术笔记

记录前端学习的点点滴滴

18 人关注