如何通过原生js实现一个节流函数和防抖函数?

js防抖


特点:


  1. 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间(非常短的时间);

  1. 当事件密集触发时,函数的触发会被频繁的推迟;

  1. 只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

如何通过原生js实现一个节流函数和防抖函数?_第1张图片

应用场景:


  • Ø输入框中频繁的输入内容,搜索或者提交信息;

  • Ø频繁的点击按钮,触发某个事件;

  • Ø监听浏览器滚动事件,完成某些特定操作;

  • Ø用户缩放浏览器的resize事件;

实现方式


第三方库实现

https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js">

手动实现(原理)

基本实现:

functiondebounce(fn, delay) {

// 1.定义一个定时器, 保存上一次的定时器

lettimer=null

// 2.真正执行的函数

const_debounce=function() {

// 取消上一次的定时器

if (timer) clearTimeout(timer)

// 延迟执行

timer=setTimeout(() => {

// 外部传入的真正要执行的函数

fn()

}, delay)

}

return_debounce

}

this绑定/事件对象

functiondebounce(fn, delay) {

// 1.定义一个定时器, 保存上一次的定时器

lettimer=null

// 2.真正执行的函数

const_debounce=function(...args) {

// 取消上一次的定时器

if (timer) clearTimeout(timer)

// 延迟执行

timer=setTimeout(() => {

// 外部传入的真正要执行的函数

fn.apply(this, args)

}, delay)

}

return_debounce

}

第一次立即执行

functiondebounce(fn, delay, immediate=false) {

// 1.定义一个定时器, 保存上一次的定时器

lettimer=null

letisInvoke=false

// 2.真正执行的函数

const_debounce=function(...args) {

// 取消上一次的定时器

if (timer) clearTimeout(timer)

// 判断是否需要立即执行

if (immediate&&!isInvoke) {

fn.apply(this, args)

isInvoke=true

} else {

// 延迟执行

timer=setTimeout(() => {

// 外部传入的真正要执行的函数

fn.apply(this, args)

isInvoke=false

}, delay)

}

}

return_debounce

}

取消功能

functiondebounce(fn, delay, immediate=false) {

// 1.定义一个定时器, 保存上一次的定时器

lettimer=null

letisInvoke=false

// 2.真正执行的函数

const_debounce=function(...args) {

// 取消上一次的定时器

if (timer) clearTimeout(timer)

// 判断是否需要立即执行

if (immediate&&!isInvoke) {

fn.apply(this, args)

isInvoke=true

} else {

// 延迟执行

timer=setTimeout(() => {

// 外部传入的真正要执行的函数

fn.apply(this, args)

isInvoke=false

timer=null

}, delay)

}

}

// 封装取消功能

_debounce.cancel=function() {

if (timer) clearTimeout(timer)

timer=null

isInvoke=false

}

return_debounce

}

函数返回值

js节流


特点:


  1. 当事件触发时,会执行这个事件的响应函数;

  1. 如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数;

  1. 不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的;

如何通过原生js实现一个节流函数和防抖函数?_第2张图片

应用场景:


Ø 游戏中的一些设计--王者荣耀 英雄的普攻;

Ø监听页面的滚动事件;

Ø 鼠标移动事件;

Ø 用户频繁点击按钮操作;

实现方式:


第三方库实现

https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js">

手动实现(原理)

基本实现:

functionthrottle(fn, interval, options) {

// 1.记录上一次的开始时间

letlastTime=0

// 2.事件触发时, 真正执行的函数

const_throttle=function() {

// 2.1.获取当前事件触发时的时间

constnowTime=newDate().getTime()

// 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数

constremainTime=interval- (nowTime-lastTime)

if (remainTime<=0) {

// 2.3.真正触发函数

fn()

// 2.4.保留上次触发的时间

lastTime=nowTime

}

}

return_throttle

}

控制开始执行一次(默认开启,后续可以通过参数来关闭)

function throttle(fn, interval, options = { leading: true, trailing: false }) {

// 1.记录上一次的开始时间

const { leading, trailing } = options

let lastTime = 0

// 2.事件触发时, 真正执行的函数

const _throttle = function() {

// 2.1.获取当前事件触发时的时间

const nowTime = new Date().getTime()

if (!lastTime && !leading) lastTime = nowTime

// 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数

const remainTime = interval - (nowTime - lastTime)

if (remainTime <= 0) {

// 2.3.真正触发函数

fn()

// 2.4.保留上次触发的时间

lastTime = nowTime

}

}

return _throttle

}

最后执行一次

function throttle(fn, interval, options = { leading: true, trailing: false }) {

// 1.记录上一次的开始时间

const { leading, trailing } = options

let lastTime = 0

let timer = null

// 2.事件触发时, 真正执行的函数

const _throttle = function() {

// 2.1.获取当前事件触发时的时间

const nowTime = new Date().getTime()

if (!lastTime && !leading) lastTime = nowTime

// 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数

const remainTime = interval - (nowTime - lastTime)

if (remainTime <= 0) {

if (timer) {

clearTimeout(timer)

timer = null

}

// 2.3.真正触发函数

fn()

// 2.4.保留上次触发的时间

lastTime = nowTime

return

}

if (trailing && !timer) {

timer = setTimeout(() => {

timer = null

lastTime = !leading ? 0: new Date().getTime()

fn()

}, remainTime)

}

}

return _throttle

}

你可能感兴趣的:(javascript,前端,开发语言)