头图

Anti-shake and throttling are frequently mentioned points in front-end performance optimization. Here is a brief introduction and implementation method.

Talk about the application scenarios of anti-shake and throttling functions, and briefly talk about the implementation

Anti-shake

  • Application scenarios of the anti-shake function: Anti-shake means that the function can only be executed once within n seconds after the event is triggered. If the event is triggered again within n seconds, the function execution time will be recalculated. Common scenarios include: anti-shake input event during real-time search by keyboard input, anti-shake event of browser window change and resize, etc.
  • Implementation method: use closure and setTimeout to achieve, create a debounce function, define a timer variable to save the timer, return a function, and manage the execution timing of the timer and fn in the function.
// 防抖函数-ES6版本
function debounce (fn, time = 200) {
    let timer = null;
    return function (...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, time);
    }
}
// 防抖函数-ES5版本
function debounceES5 (fn, time) {
    time = time || 200;
    var timer = null;
    return function () {
        if (timer) clearTimeout(timer);
        var that = this;
        var args = arguments;
        timer = setTimeout(function () {
            fn.apply(that, args);
        }, time);
    }
}
// 立即执行版本
// 有时希望⽴刻执⾏函数,然后等到停⽌触发 n 秒后,才可以重新触发执⾏。
function debounceNow (fn, time = 200, immediate = false) {
    let timer = null;
    return function (...args) {
        if (timer) clearTimeout(timer);
        if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, time);
            if (callNow) fn.apply(this, args);
        } else {
            timer = setTimeout(() => {
                fn.apply(this, args);
            }, time);
        }
    }
}
// 返回值版实现
// 只在 immediate 为 true 的时候返回函数的执⾏结果。
function debounceReturn (fn, time = 200, immediate = false) {
    let timer, result;
    return function (...args) {
        if (timer) clearTimeout(timer);
        if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, timer);
            if (callNow) result = fn.apply(this, args);
        } else {
            timer = setTimeout(() => {
                fn.apply(this, args);
            }, time);
        }
        return result;
    }
}
<div>
    <span>测试防抖 debounce</span>
    <input type="text" id="input_1">
</div>
// 测试防抖
let input_1 = document.getElementById('input_1');
input_1.addEventListener('input', debounce(function (event) {
    console.log('event = ', event); // InputEvent 事件对象
    console.log('this = ', this); // input_1 的DOM对象
}));
// 测试防抖传参
// input_1.addEventListener('input', debounce(function (a, b, event) {
//     console.log('a = ', a); // 1
//     console.log('b = ', b); // 2
//     console.log('event = ', event); // InputEvent 事件对象
//     console.log('this = ', this); // input_1 的DOM对象
// }).bind(input_1, 1, 2) );

function handle (a) {
    console.log('handle');
    console.log(a);
}
let debounceHandle = debounceES5(handle, 1000);

// 防抖函数参数
// let timer = setInterval(debounceHandle, 200);
let timer = setInterval(() => { debounceHandle(1) }, 200);
setTimeout(function() {
    clearInterval(timer);
}, 2000);
// 输出:2秒后,打印出 handle 1

Throttling

  • The application scenario of the throttling function: throttling means that the same event is triggered continuously within a continuous period of time, and the event will be executed only once every n seconds. Common scenarios include: lazy loading needs to monitor and calculate the position of the scroll bar, and the user can only click the submit button once within a certain period of time, and so on.
  • Implementation method: use closure and setTimeout with an identifier to implement, create a throttle function, define a canRun variable to save whether the task is executable, return a function, manage the value of canRun and the execution timing of fn in the function , And return directly when canRun is false.
// 节流函数-ES6版本
function throttle (fn, time = 200) {
    let canRun = true;
    return function (...args) {
        if (!canRun) return;
        canRun = false;
        setTimeout(() => {
            fn.apply(this, args);
            canRun = true;
        }, time);
    }
}
// 节流函数-ES5版本
function throttleES5 (fn, time) {
    time = time || 200;
    var canRun = true;
    return function () {
        if (!canRun) return;
        canRun = false;
        var that = this;
        var args = arguments;
        setTimeout(function () {
            fn.apply(that, args);
            canRun = true;
        }, time);
    }
}
<div>
    <span>测试节流 throttle</span>
    <input type="text" id="input_2">
</div>
// 测试节流
let input_2 = document.getElementById('input_2');
input_2.addEventListener('input', throttle(function (event) {
    console.log('event = ', event); // InputEvent 事件对象
    console.log('this = ', this); // input_2 的DOM对象
}));
// 测试节流传参
// input_2.addEventListener('input', throttle(function (a, b, event) {
//     console.log('a = ', a); // 1
//     console.log('b = ', b); // 2
//     console.log('event = ', event); // InputEvent 事件对象
//     console.log('this = ', this); // input_2 的DOM对象
// }).bind(input_2, 1, 2) );

lxcan
337 声望32 粉丝