JS防抖和节流

防抖和节流是前端性能优化中经常提及的点,下面来做个简单介绍和实现方式。

说一下防抖和节流函数的应用场景,并简单说下实现方式

防抖

  • 防抖函数的应用场景:防抖是指,触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。常见场景有:键盘输入实时搜索时input事件防抖,浏览器窗口改变resize事件防抖等等。
  • 实现方式:利用闭包和setTimeout来实现,创建一个debounce函数,定义一个timer变量用来保存定时器,返回一个函数,在函数内管理定时器和fn的执行时机。
// 防抖函数-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);
    }
}
测试防抖 debounce
// 测试防抖
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

节流

  • 节流函数的应用场景:节流是指,在连续的时间内不断触发同个事件,会每隔 n 秒才执行一次这个事件。常见场景有:懒加载要监听计算滚动条的位置,用户点击提交按钮只允许一定时间内点击一次等等。
  • 实现方式:利用闭包和setTimeout配合一个标识符来实现,创建一个throttle函数,定义一个canRun变量用来保存当次任务是否可执行,返回一个函数,在函数内管理canRun的值和fn的执行时机,当canRun为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);
    }
}
测试节流 throttle
// 测试节流
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) );

你可能感兴趣的:(javascript性能优化)