函数节流

113 阅读1分钟

一、简洁版 1、函数节流:

  • 设置一个WAIT时间,此时间是用户自己定义,多久内触发多次算是频繁触发

  • 函数节流:在频繁触发的模式下,我们每间隔WAIT这么久,就触发一次「节流的目的是降低触发频率」

     function throttle(fun, wait) {
             var timer = null,
                 previous = 0;
             return function proxy() {
                 var self = this,
                     params = [].slice.call(arguments)
                 var now = + new Date()
                 var remain = wait - (now - previous)
                 if (remain < 0) {
                     if (timer) {
                         clearTimeout(timer);
                         timer = null;
                     }
                     fun.apply(self, params)
                     previous = now
                 }
                 if (!timer) {
                     timer = setTimeout(function () {
                         clearTimeout(timer)
                         timer = null
                         fun.apply(self, params)
                         previous = now
                     }, remain)
                 }
             }
         }
    

2、整体调用

  <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
</body>

</html>
<script>

</script>
<style>
    * {
        margin: 0;
        padding: 0;
    }

    html,
    body {
        height: 500%;
        background: -webkit-linear-gradient(top left, pink, orange, lightblue, yellow);
    }
</style>
<script>
    //函数节流:让两次函数执行的时间间隔要超过wait
    //相隔时间在wait之间
    function throttle(fun, wait) {
        var timer = null,
            previous = 0;
        return function proxy() {
            var self = this,
                params = [].slice.call(arguments)
            var now = + new Date()
            var remain = wait - (now - previous)
            if (remain < 0) {
                if (timer) {
                    clearTimeout(timer);
                    timer = null;
                }
                fun.apply(self, params)
                previous = now
            }
            if (!timer) {
                timer = setTimeout(function () {
                    clearTimeout(timer)
                    timer = null
                    fun.apply(self, params)
                    previous = now
                }, remain)
            }
        }
    }
    function bundle(ev) {
        console.log(ev)
    }
    window.onscroll = throttle(bundle, 1000)
</script>

二、复杂版

/*
 * 设置一个WAIT时间,此时间是用户自己定义,多久内触发多次算是频繁触发
 * 函数节流:在频繁触发的模式下,我们每间隔WAIT这么久,就触发一次「节流的目的是降低触发频率」
 */
function throttle(func, wait) {
    if (typeof func !== "function") throw new TypeError('func must be a function!');
    wait = +wait;
    if (isNaN(wait)) wait = 300;
    var timer = null,
        previous = 0
    return function proxy() {
        var self = this,
            params = [].slice.call(arguments);
        var now = +new Date,
            remaining = wait - (now - previous),
            result
        if (remaining <= 0) {
            // 两次间隔时间已经超过WAIT了,此时我们立即执行
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            previous = now;
           result = func.apply(self, params);
           return result
        }
        // 没有定时器我们才设置,有定时器说明上次还没执行呢,只有上一次执行了,我们在开启下一次
        if (!timer) {
            timer = setTimeout(function () {
                clearTimeout(timer);
                timer = null;
                previous = +new Date;
                result = func.apply(self, params);
            }, remaining);
            return result
        }
    };
}

// 监听滚动条滚动,触发执行方法「问题:滚动条滚动中,浏览器最快的反应时间内则会触发一次  谷歌:5~6ms  IE:10~17ms」
window.onscroll = throttle(handle);
// window.onscroll = proxy;  每间隔5~6ms触发一次proxy,但是最后执行的还是handle,我们在proxy中能够控制handle执行的频率即可