js 防抖 节流 JavaScript

js 防抖 节流 JavaScript

实际工做中,经过监听某些事件,如scroll事件检测滚动位置,根据滚动位置显示返回顶部按钮;如resize事件,对某些自适应页面调整DOM的渲染;如keyup事件,监听文字输入并调用接口进行模糊匹配等等,这些事件处理函数调用的频率若是过高,会加剧浏览器的负担,减弱性能,形成用户体验很差。此时须要采用debounce(防抖)和throttle(节流)的方式来减小调用频率,同时不影响原来效果。javascript

函数防抖(debounce)

当持续触发事件时,一段时间段内没有再触发事件,事件处理函数才会执行一次,若是设定的时间到来以前就触发了事件,延时从新开始。
函数防抖的应用场景,最多见的就是用户注册时候的手机号码验证和邮箱验证了。只有等用户输入完毕后,前端才须要检查格式是否正确,若是不正确,再弹出提示语。前端

clipboard.png

上图中,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件;
上面原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。
代码以下:java

// 函数防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
    clearTimeout(timer); // 清除未执行的代码,重置回初始化状态

    timer = setTimeout(function(){
        console.log("函数防抖");
    }, 1000);
};

防抖函数的封装使用浏览器

/**
 * 防抖函数
 * @param method 事件触发的操做
 * @param delay 多少毫秒内连续触发事件,不会执行
 * @returns {Function}
 */
function debounce(method,delay) {
    let timer = null;
    return function () {
        let self = this,
            args = arguments;
        timer && clearTimeout(timer);
        timer = setTimeout(function () {
            method.apply(self,args);
        },delay);
    }
}
window.onscroll = debounce(function () {
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
},1000)

另外一种写法app

// 防抖
function debounce(fn, wait) {    
    var timeout = null;    
    return function() {        
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}
// 处理函数
function handle() {    
    console.log("函数防抖"); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));

函数节流(throttlo)

当持续触发事件时,保证必定时间段内只调用一次事件处理函数。
函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。函数

clipboard.png

上图中,持续触发scroll事件时,并不当即执行handle函数,每隔1000毫秒才会执行一次handle函数;
函数节流的要点是,声明一个变量当标志位,记录当前代码是否在执行。若是空闲,则能够正常触发方法执行。
代码以下:性能

// 函数节流 定时器
var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,若是在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};

节流函数的封装使用this

//节流throttle代码(时间戳)
var throttle = function(func, delay) {            
  var prev = Date.now();            
  return function() {                
    var context = this;                
    var args = arguments;                
    var now = Date.now();                
    if (now - prev >= delay) {                    
      func.apply(context, args);                    
      prev = Date.now();                
    }            
  }        
}        
function handle() {            
  console.log("函数节流");        
}        
window.addEventListener('scroll', throttle(handle, 1000));


//节流throttle代码(定时器)
var throttle = function(func, delay) {            
    var timer = null;            
    return function() {                
        var context = this;               
        var args = arguments;                
        if (!timer) {                    
            timer = setTimeout(function() {                        
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}        
function handle() {            
    console.log("函数节流");        
}        
window.addEventListener('scroll', throttle(handle, 1000));


// 节流throttle代码(时间戳+定时器):
var throttle = function(func, delay) {     
    var timer = null;     
    var startTime = Date.now();     
    return function() {             
        var curTime = Date.now();             
        var remaining = delay - (curTime - startTime);             
        var context = this;             
        var args = arguments;             
        clearTimeout(timer);              
        if (remaining <= 0) {                    
            func.apply(context, args);                    
            startTime = Date.now();              
        } else {                    
            timer = setTimeout(func, remaining);              
        }      
    }
}
function handle() {      
    console.log("函数节流");
} 
window.addEventListener('scroll', throttle(handle, 1000));

用时间戳+定时器,当第一次触发事件时立刻执行事件处理函数,最后一次触发事件后也还会执行一次事件处理函数spa

欢迎关注

相关文章
相关标签/搜索