JavaScript函数防抖、节流、柯里化

184 阅读1分钟

防抖

频繁触发的函数,只会执行最后一次

应用场景:表单验证、模糊查询等

function debounce(fn, timeout = 300) {
    let timer;
    
    return function () {
        let context = this;
        let args = arguments;
        
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
            fn && fn.apply(context, args);
        }, timeout);
    }
}

节流

频繁触发的函数,在一段时间内只执行一次

应用场景:如鼠标移动事件等

function throttle(fn, timeout = 300) {
    let timer;
    
    return function () {
        let context = this;
        let args = arguments;
        
        if(!timer) {
            timer = setTimeout(function () {
                fn && fn.apply(context, args);
                clearTimeout(timer);
                timer = null;
            }, timeout);
        }
    }
}

柯里化

将接收多个参数的函数变为只接受一个单一的参数的函数,并返回接收余下参数的函数和返回结果的新函数

应用场景:延迟计算,参数复用,动态生成函数

// 例子

// 原函数,用来返回参数a + 参数b 的结果
function increment(a, b) {
    return a + b;
}

// 将increment函数柯里化之后
function curryingIncrement(a) {
    // 只接受一个参数,返回一个接收余下参数的函数
    return function (b) {
        // 被返回的函数返回了计算结果的新函数
        return function() {
            return a + b;
        };
    }
}

increment(10, 20); // 30

// 柯里化后执行如下
curryingIncrement(10)(20); // 30

封装代码

function currying(fn) {
    let args = [];
    // 返回一个命名的函数便于递归使用,也可以使用arguments.callee,但是这在严格模式下禁用
    return function next() {
        let arg = arguments;
        args = [...args, ...arg];
        // 若参数个数大于0 返回next
        if(arg.length > 0) {
            return next;
        } else {
            // 参数格式等于0,返回计算结果的函数
            let context = this;
            return fn.apply(context, args);
        }
    };
}

// ===== 测试函数功能 ===== //

// 原函数, 功能:返回参数相加的结果
function increment() {
    let args = arguments;
    let result = 0;
    for (let i = 0; i < args.length; i++) {
        result += args[i];
    }
    return result;
}

// 柯里化之后
let add = currying(increment);
add(10, 10, 10)(20)(30)(); // 80