debounce & throttle function

debounce

/**
 * 防抖函数 (Debounce)
 * @param {Function} fn - 需要执行的函数
 * @param {Number} delay - 延迟时间(ms)
 */
function debounce(fn, delay) {
    let timer = null; // 1. 闭包保存定时器

    return function(...args) {
        // 2. 如果定时器还在,说明上一次还没执行完,清除它
        if (timer) clearTimeout(timer);

        // 3. 重新开启定时器,delay 时间后执行
        timer = setTimeout(() => {
            // 4. 这里的箭头函数自动穿透,拿到外层的 this
            fn.apply(this, args);
        }, delay);
    }
}

throttle

/**
 * 节流函数 (Throttle)
 * @param {Function} fn - 需要执行的函数
 * @param {Number} delay - 间隔时间(ms)
 */
function throttle(fn, delay) {
    let timer = null; // 1. 闭包保存定时器标志

    return function(...args) {
        // 2. 如果定时器存在,说明还在"冷却中",直接返回
        if (timer) return;

        // 3. 开启定时器(上锁)
        timer = setTimeout(() => {
            // 4. 时间到了,执行函数
            fn.apply(this, args);
            
            // 5. 关键:执行完后,把定时器清空(解锁),允许下一次触发
            timer = null;
        }, delay);
    }
}

Example Code

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta
        name="viewport"
        content="width=device-width, initial-scale=1.0"
    >
    <title>Debounce & Throttle</title>
    <style>
        body {
            font-family: sans-serif;
            padding: 20px;
            line-height: 1.6;
        }

        .container {
            margin-bottom: 30px;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 8px;
        }

        .box {
            width: 100%;
            height: 200px;
            background-color: #f0f4f8;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            color: #333;
            cursor: crosshair;
            border: 2px dashed #007bff;
        }

        input {
            padding: 10px;
            width: 300px;
            font-size: 16px;
        }

        strong {
            color: #d9534f;
        }
    </style>
</head>

<body>

    <h1>前端面试:手写防抖与节流</h1>

    <div class="container">
        <h3>1. 防抖 (Debounce) 示例</h3>
        <p>场景:搜索框。请在下方连续输入文字,观察 "触发结果"。</p>
        <input
            type="text"
            id="debounceInput"
            placeholder="尝试连续快速输入..."
        >
        <p>实际触发结果:<strong id="debounceResult">等待输入...</strong></p>
    </div>

    <div class="container">
        <h3>2. 节流 (Throttle) 示例</h3>
        <p>场景:鼠标移动。请在下方蓝色区域内快速移动鼠标。</p>
        <div
            id="throttleBox"
            class="box"
        >
            鼠标在这里移动
        </div>
        <p>计数器 (每1秒更新一次):<strong id="throttleResult">0</strong></p>
    </div>

    <script>
        // ==============================
        // 1. 手写防抖函数
        // ==============================


        function debounce(fn, delay) {
            let timer = null
            return function (...args) {
                if (timer) clearTimeout(timer)
                timer = setTimeout(() => {
                    fn.apply(this, args)
                }, delay)
            }
        }

        // ==============================
        // 2. 手写节流函数
        // ==============================
        function throttle(fn, delay) {
            let timer = null
            return function (...args) {
                if (timer) return  //冷却中 不执行
                timer = setTimeout(() => {
                    fn.apply(this, args)
                    timer = null //解锁
                }, delay)
            }
        }

        // ==============================
        // 业务逻辑绑定
        // ==============================

        // 1. 防抖测试逻辑
        const inputEl = document.getElementById('debounceInput');
        const debounceResultEl = document.getElementById('debounceResult');

        // 定义要执行的业务函数
        function handleInput(e) {
            console.log('防抖触发:', e.target.value);
            debounceResultEl.innerText = `发送请求: ${e.target.value} (${new Date().toLocaleTimeString()})`;
        }

        // 绑定事件:延迟 1000ms 执行
        inputEl.addEventListener('input', debounce(handleInput, 1000));

        // 2. 节流测试逻辑
        const boxEl = document.getElementById('throttleBox');
        const throttleResultEl = document.getElementById('throttleResult');
        let count = 0;

        // 定义要执行的业务函数
        function handleMouseMove(e) {
            count++;
            console.log('节流触发 count:', count);
            throttleResultEl.innerText = count;
            boxEl.innerText = `X: ${e.offsetX}, Y: ${e.offsetY}`;
        }

        // 绑定事件:每 1000ms 最多执行一次
        boxEl.addEventListener('mousemove', throttle(handleMouseMove, 1000));

    </script>
</body>

</html>
Life's a struggle, I'll conquer it.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇