目录
一、防抖
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
}