手写防抖/节流/深拷贝

目录

一、防抖

1.1 基本使用

1.2 新增第一次立即执行

1.3 新增取消功能

 1.4 新增返回值功能

二、节流

2.1 基本使用

2.2 新增第一次不立即执行

2.3 新增最后一次不执行

2.4 新增取消功能

2.5 新增返回值功能

三、深拷贝


一、防抖

1.1 基本使用

const debounce = function (fn, delay) {
    let timer = null

    const _debounce = function (...args) {
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            // 绑定this,传入event
            fn.apply(this, args)
        }, delay);
    }

    return _debounce
}

1.2 新增第一次立即执行

const debounce = function (fn, delay, immediately = false) {
    let timer = null
    let isOnce = true
    const _debounce = function (...args) {
        if (timer) clearTimeout(timer)
        // 如果三参为true,就立即执行
        if (isOnce && immediately) {
            fn.apply(this, args)
            isOnce = false
        } else {
            timer = setTimeout(() => {
                // 绑定this,传入event
                fn.apply(this, args)
                isOnce = true
            }, delay);
        }

    }

    return _debounce
}

1.3 新增取消功能

在内部写一个取消函数,直接调用就行了

const debounce = function (fn, delay, immediately = false) {
    let timer = null
    let isOnce = true
    const _debounce = function (...args) {
        if (timer) clearTimeout(timer)
        // 如果三参为true,就立即执行
        if (isOnce && immediately) {
            fn.apply(this, args)
            isOnce = false
        } else {
            timer = setTimeout(() => {
                // 绑定this,传入event
                fn.apply(this, args)
                isOnce = true
            }, delay);
        }

    }

    // 取消功能
    _debounce.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        isOnce = true
    }

    return _debounce
}

 1.4 新增返回值功能

给第四参搞一个回调函数

调用的时候,debounce(fn, 2000, false, (res) => { console.log('res返回值', res); })

/**
 * 防抖
 * @param {function}函数 fn 
 * @param {number}延迟多少毫秒 delay 
 * @param {boolean}是否立即执行一次,默认值false immediately 
 * @param {function}回调函数,返回值 resFn 
 * @returns 
 */
const debounce = function (fn, delay, immediately = false, resFn) {
    let timer = null
    let isOnce = true
    const _debounce = function (...args) {
        if (timer) clearTimeout(timer)
        if (isOnce && immediately) {
            const res = fn.apply(this, args)
            if (resFn) resFn(res)
            isOnce = false
        } else {
            timer = setTimeout(() => {
                const res = fn.apply(this, args)
                if (resFn) resFn(res)
                isOnce = true
            }, delay);
        }
    }
    // 取消功能
    _debounce.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        isOnce = true
    }
    return _debounce
}

二、节流

2.1 基本使用

const throttle = function (fn, interval) {
    let lastTime = 0
    const _throttle = function () {
        //获取当前的时间
        let nowTime = new Date().getTime()
        //每当执行该函数,就用间隔的时间减去(当点击后一直到下一次间隔的间隙)
        //(即,当前时间减去上一次执行的时间,等于上一次执行后到现在之间的时间)
        const remainTime = interval - (nowTime - lastTime)
        //如果再次执行的时间,是负数,那么就执行一次
        if (remainTime <= 0) {
            fn()
            lastTime = nowTime
        }
    }
    return _throttle
}

2.2 新增第一次不立即执行

const throttle = function (fn, interval, immediately = true) {
    let lastTime = 0
    const _throttle = function () {
        let nowTime = new Date().getTime()
        // 当nowTime和lastTime都是当前时间,那么第一次就不会执行
        if (!lastTime && !immediately) lastTime = nowTime
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            fn()
            lastTime = nowTime
        }
    }
    return _throttle
}

2.3 新增最后一次不执行

const throttle = function (fn, interval, immediately = true, lastOnce = false) {
    let lastTime = 0
    let timer = null
    const _throttle = function () {
        let nowTime = new Date().getTime()
        if (!lastTime && !immediately) lastTime = nowTime
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            // 3.如果当前有定时器,要取消掉,因为我们只需要执行最后一次定时器
            if (timer) {
                clearTimeout(timer)
                timer = null
            }
            fn()
            lastTime = nowTime
            // 2.当触发了,就不需要加定时器
            return
        }
        //思路:1.给剩余时间添加定时间
        if (lastOnce && !timer) {
            timer = setTimeout(() => {
                timer = null
                // 4.当第一次是否执行,如果第一次执行的话,那么lastTime就给0,否则给当前时间
                lastTime = !immediately ? 0 : new Date().getTime()
                fn()
            }, remainTime)
        }
    }
    return _throttle
}

2.4 新增取消功能

const throttle = function (fn, interval, immediately = true, lastOnce = false) {
    let lastTime = 0
    let timer = null
    const _throttle = function (...args) {
        let nowTime = new Date().getTime()
        if (!lastTime && !immediately) lastTime = nowTime
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            if (timer) {
                clearTimeout(timer)
                timer = null
            }
            fn.apply(this, args)
            lastTime = nowTime
            return
        }
        if (lastOnce && !timer) {
            timer = setTimeout(() => {
                timer = null
                lastTime = !immediately ? 0 : new Date().getTime()
                fn.apply(this, args)
            }, remainTime)
        }
    }
    // 取消功能
    _throttle.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        lastTime = 0
    }
    return _throttle
}

2.5 新增返回值功能

给第五参搞一个回调函数,调用同1.4一样

/**
 * 节流
 * @param {function}函数 fn 
 * @param {number}间隔时间 interval 
 * @param {boolean}第一次是否执行,默认值true immediately 
 * @param {boolean}最后一次是否执行,默认值false lastOnce 
 * @param {function}回调函数,返回值 resFn 
 * @returns 
 */
const throttle = function (fn, interval, immediately = true, lastOnce = false, resFn) {
    let lastTime = 0
    let timer = null
    const _throttle = function (...args) {
        let nowTime = new Date().getTime()
        if (!lastTime && !immediately) lastTime = nowTime
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            if (timer) {
                clearTimeout(timer)
                timer = null
            }
            const res = fn.apply(this, args)
            if (resFn) resFn(res)
            lastTime = nowTime
            return
        }
        if (lastOnce && !timer) {
            timer = setTimeout(() => {
                timer = null
                lastTime = !immediately ? 0 : new Date().getTime()
                const res = fn.apply(this, args)
                if (resFn) resFn(res)
            }, remainTime)
        }
    }
    // 取消功能
    _throttle.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        lastTime = 0
    }
    return _throttle
}

三、深拷贝

function isObject(value) {
    const valueType = typeof value
    return (value !== null) && (valueType === 'object' || valueType === 'function')
}
const deepClone = function (value) {
    if (typeof value !== 'function') return value
    if (!isObject(value)) return value
    const newValue = Array.isArray(value) ? [] : {}
    for (const key in value) {
        newValue[key] = deepClone(value[key])
    }
    return newValue
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值