函数防抖和节流

定义

在JS里,有一些事件是很容易频繁触发的,比如窗口的resizescroll、鼠标的onmousemove等操作,在事件频繁触发的过程中,不可避免的导致频繁执行触发事件中的函数。为了防止这种情况的发生,主流的解决方案有两种,防抖debounce)和节流(throttle)

频繁执行情况

            var num = 1;
            var moveCntent = document.getElementById('example')
            function count(){
                moveCntent.innerHTML++;
            }
            moveCntent.onmousemove = count

效果如下:


函数防抖和节流_第1张图片

可以明显的看到,count 函数执行的非常频繁,假如现在我们count函数里执行的是一个Ajax请求,那么问题就会非常严重了。

防抖

函数防抖就是在一段时间(n毫秒)触发或调用函数时,只执行一次; 也可以理解为触发n毫秒之后才会调用一次。

防抖函数的写法主要有两种,非立即执行版本立即执行版本

非立即执行版

                var num = 1;
                var moveCntent = document.getElementById('example')
                function count(){
                        moveCntent.innerHTML++;
                }
                moveCntent .onmousemove = count
                function debounce(fn,delay){
                        var timer;
                        return function(){
                            var _this = this;
                            var args = arguments;
                            if(timer) clearTimeout(timeout);
                            timer = setTimeout(function(){
                                fn.apply(_this,args)
                            },delay)
                            }
                    }
                moveCntent.onmousemove = debounce(count,1000)

原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

效果如下:


函数防抖和节流_第2张图片

在触发事件1秒后才执行,如果在触发事件的一秒内又触发了事件,则重新计算函数执行时间

立即执行版

                function debounce(fn,delay){
                    var timer;
                    return function(){
                        var _this = this;
                        var args = arguments;
                        if(timer){
                            clearTimeout(timer);
                        } 
                        if(!timer){
                            fn.apply(_this,args);
                        } 
                        timer = setTimeout(function(){
                            timer = null;
                        },delay);
                    };
                }

立即执行版本和非例行版本的区别是:

  • 立即执行版本:触发事件后函数立即执行,然后n秒内不触发时间才会继续执行
  • 非立即执行版本:触发事件后函数不会立即执行,而是在n秒回才会执行

节流

函数节流,就是指连续触发的事件在n秒钟只执行一次函数。降低函数的执行频率,对于函数节流,通常也也有两种方式实现,分别是时间戳版定时器版

时间戳版

                function throttle(fn,delay){
                    var previous = 0;
                    return function(){
                        var now = Date.now();
                        var _this = this;
                        var args = arguments;
                        if(now - previous > delay){
                            fn.apply(_this,args);
                            previous = now;
                        }
                    };
                }
                moveCntent.onmousemove = throttle(count,1000)

当高频事件触发时,第一次会立即执行,而后再怎么频繁地触发事件,也都是每delay时间才执行一次。

效果如下:


函数防抖和节流_第3张图片

持续触发事件的过程中,函数会立即执行,并且每一秒执行一次

定时器版

                function throttle(fn,delay){
                    var timer;
                    return function(){
                        var _this = this;
                        var args = arguments;
                        if(!timer){
                            timer = setTimeout(function(){
                                timer = null;
                                fn.apply(_this,args);
                            },delay);
                        }
                    };
                }

在持续触发事件的过程中,函数不会立即执行,并且每一秒执行一次,停止触发事件后,还会再执行一次

效果如下:


函数防抖和节流_第4张图片

时间戳版本和定时器版本的区别是:

  • 时间戳版本:触发事件后函数立即执行,每n秒执行一次
  • 定时器版本:触发事件后函数不会立即执行,每n秒执行一次,停止触发后还会执行一次

总结

函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

你可能感兴趣的:(函数防抖和节流)