前端的常见开发思想

本文详细介绍了JavaScript中的柯里化技术,以及如何通过节流和防抖优化高频事件处理,如窗口滚动和输入事件,以提高性能并控制函数执行频率。
摘要由CSDN通过智能技术生成

柯里化

(颗粒化)
作用:参数复用、延迟执行、函数组合

function uri_curring(protocol) {
    return function (hostname, pathname) {
        return `${protocol}://${hostname}/${pathname}`
    }
}

// 生成一个https的uri,可用于多次调用
const uri_https = uri_curring('https');

const uri1 = uri_https('www.baidu1.com', 'index1.html');
const uri2 = uri_https('www.baidu2.com', 'index2.html');

console.log(uri1); // https://www.baidu1.com/index1.html
console.log(uri2); // https://www.baidu2.com/index2.html
/**
 * 实现柯里化函数
 * @param {Function} fn 要柯里化的函数
 * @param  {...any} args 初始参数
 * @returns {Function} 柯里化后的函数
 */
function curry(fn, ...args) {
    // 获取函数参数个数
    let len = fn.length;
    // 如果传入的参数数量大于或等于函数参数个数,则直接调用函数
    if (args.length >= len) return fn(...args);
    // 否则返回一个新函数,继续接受新的参数
    return function (...newArgs) {
        // 合并之前的参数和新参数
        let _args = args.concat(newArgs);
        // 递归调用 curry 函数
        return curry.call(this, fn, ..._args);
    }
}

节流防抖

节流

触发高频事件,但在n秒内只会执行一次,在于稀释函数的执行频率,侧重于一段时间内只执行一次

(就像游戏里无论手速多快,多次平A也有频率上限)

应用场景:

  • window对象的resize、scroll事件
  • 拖拽事件的mousemove
  • 射击游戏中的mousedown、keydown事件
  • 文字输入、自动完成的keyup事件

防抖

触发高频事件后,n秒内只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间,侧重于一段时间内多次触发只在最后执行一次

(就像游戏里释放技能的时候,再按一次技能就会重新冷却)

应用场景:

  • 提交按钮、用户注册时候的手机号验证、邮箱验证
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            height: 4000px;
            background-color: #000;
        }
    </style>
</head>

<body>
    <input id="input"></input>
    <div id="div"></div>

    <script>
        function sendRequest() {
            console.log("发送请求");
        }

        // 节流:
        // document.getElementById("div").onscroll = throttle(sendRequest, 1000)

        const onscroll = throttle(sendRequest, 1000)

        function throttle(fn, delayTime) {
            let valve = true;
            return function () {
                if (!valve) {
                    return;
                }
                valve = false;
                setTimeout(() => {
                    fn && fn()
                    valve = true;
                }, delayTime)
            }
        }

        // 防抖:输入完成后间隔一秒再发送请求
        document.getElementById("input").oninput = antiShake(sendRequest, 1000);

        function antiShake(fn, delayTime) {
            let timer = null;
            return function () {
                if (timer) {
                    clearTimeout(timer)
                };
                timer = setTimeout(() => {
                    fn && fn();
                }, delayTime)
            };
        }
    </script>
</body>

</html>

手写节流

function throttle(callback, delayTime, leading = false, trailing = true) {
    let state = true;
    let timer = null;
    
    // 参数类型检查
    if (typeof callback !== 'function' || typeof delayTime !== 'number' || typeof leading !== 'boolean' || typeof trailing !== 'boolean') {
        console.error('throttle() 传入参数类型错误');
        return;
    };
    
    // 使用...args保留所有参数
    return function (...args) {
        // 立即执行
        if (leading && state) {
            state = false;
            setTimeout(() => {
                // 使用apply()保留this指向
                callback && callback.apply(this, args);
                state = true;
            }, delayTime)
        }
        // 延迟执行
        if (!timer) {
            timer = setTimeout(() => {
                if (trailing) callback && callback.apply(this, args);
                state = true;
                timer = null;
            }, delayTime)
        }
    }
};

手写防抖

function debounce(callback, delayTime, immediate = false) {
    if (typeof callback !== 'function' || typeof delayTime !== 'number') {
        console.error('debounce() 传入参数类型错误');
        return;
    }
    let timer = null;

    // 返回一个函数,用于取消防抖
    const debounced = function (...args) {
        if (immediate && !timer) {
            // 立即执行
            callback.apply(this, args);
        }
        clearTimeout(timer);
        timer = setTimeout(() => {
            callback.apply(this, args);
            timer = null;
        }, delayTime);
    };

    // 取消防抖
    debounced.cancel = function () {
        clearTimeout(timer);
        timer = null;
    };

    return debounced;
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘泽宇Developer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值