每日前端进阶第五题:防抖(debounce)函数的作用是什么?有哪些应用场景,请实现一个防抖函数。
栏目: JavaScript · 发布时间: 5年前
内容简介:防抖是什么?防抖就是防止抖动,例如小朋友喜欢多动,停不下来,然后做家长的打一顿,让小朋友安静下来,这种行为就叫做防抖。(~o ̄3 ̄)~抖个机灵,哈哈哈~
防抖是什么?防抖就是防止抖动,例如小朋友喜欢多动,停不下来,然后做家长的打一顿,让小朋友安静下来,这种行为就叫做防抖。
(~o ̄3 ̄)~
抖个机灵,哈哈哈~
抖动是一个很常见的控制函数在一定时间内执行多少次的技巧,其实就是确定了函数执行的最小间隔,如果还在这个间隔内触发函数,则重新计算。
举个栗子~
你家有七个儿子,大儿子叫大娃,二儿子叫二娃,三儿子叫三娃,四儿子叫四娃,五儿子叫五娃,六儿子叫六娃,七儿子叫七娃。由于七个孩子还小,他们的衣服你只能用手洗,一洗洗七套,一次要一个小时。如果洗到一半,你的七个孩子给你过来捣乱把衣服弄脏,那么你又得花一个小时去洗,不捣乱,那么你一个小时之后你的孩子衣服就又脏了,又可以再花一个小时来洗衣服了。
具体实现
鱼头注:以下代码来自优秀的JS库 lodash
// 判断是不是个对象 function isObject(value) { const type = typeof value return value != null && (type == 'object' || type == 'function') } /* * 创建一个 debounced 函数,延迟调用 func 直到 wait 之后 * cancel 方法用于取消 debounced * flush 方法用于立即调用 */ function debounce(func, wait, options) { let lastArgs, lastThis, maxWait, result, timerId, lastCallTime let lastInvokeTime = 0 let leading = false let maxing = false let trailing = true // 绕过 requestAnimationFrame ,显式地设置 wait = 0 const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function') if (typeof func !== 'function') { throw new TypeError('Expected a function') } wait = +wait || 0 if (isObject(options)) { leading = !!options.leading maxing = 'maxWait' in options maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait trailing = 'trailing' in options ? !!options.trailing : trailing } function invokeFunc(time) { const args = lastArgs const thisArg = lastThis lastArgs = lastThis = undefined lastInvokeTime = time result = func.apply(thisArg, args) return result } function startTimer(pendingFunc, wait) { if (useRAF) { root.cancelAnimationFrame(timerId); return root.requestAnimationFrame(pendingFunc) } return setTimeout(pendingFunc, wait) } function cancelTimer(id) { if (useRAF) { return root.cancelAnimationFrame(id) } clearTimeout(id) } function leadingEdge(time) { // 重置任何 最大等待时间的计时器 lastInvokeTime = time // 启动计时器 timerId = startTimer(timerExpired, wait) // 返回调用结果 return leading ? invokeFunc(time) : result } function remainingWait(time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime const timeWaiting = wait - timeSinceLastCall return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting } function shouldInvoke(time) { const timeSinceLastCall = time - lastCallTime const timeSinceLastInvoke = time - lastInvokeTime // 判断是否应该调用函数 return (lastCallTime === undefined || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) } function timerExpired() { const time = Date.now() if (shouldInvoke(time)) { return trailingEdge(time) } // 重置定时器 timerId = startTimer(timerExpired, remainingWait(time)) } function trailingEdge(time) { timerId = undefined // 如果我有最后一个参数,就意味着函数需要调用 // 至少执行一次防抖 if (trailing && lastArgs) { return invokeFunc(time) } lastArgs = lastThis = undefined return result } function cancel() { if (timerId !== undefined) { cancelTimer(timerId) } lastInvokeTime = 0 lastArgs = lastCallTime = lastThis = timerId = undefined } function flush() { return timerId === undefined ? result : trailingEdge(Date.now()) } function pending() { return timerId !== undefined } function debounced(...args) { const time = Date.now() const isInvoking = shouldInvoke(time) lastArgs = args lastThis = this lastCallTime = time if (isInvoking) { if (timerId === undefined) { return leadingEdge(lastCallTime) } if (maxing) { // 处理循环调用 timerId = startTimer(timerExpired, wait) return invokeFunc(lastCallTime) } } if (timerId === undefined) { timerId = startTimer(timerExpired, wait) } return result } debounced.cancel = cancel debounced.flush = flush debounced.pending = pending return debounced } 复制代码
使用方法如下:
var 打印一些东西啦 = function (event) { console.log(event); }; document.querySelector('html').addEventListener('click', debounce(打印一些东西啦, 1000)); 复制代码如果你、喜欢探讨技术,或者对本文有任何的意见或建议,你可以扫描下方二维码,关注微信公众号“
”,随时与鱼头互动。欢迎!衷心希望可以遇见你。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端笔记(关于箭头函数与普通函数的区别的理解)
- 前端Vue:函数式组件
- 前端面试ES6系列:箭头函数和普通函数的区别
- 函数劫持能做啥?前端黑科技揭秘
- 开发自己的前端工具库(二):函数式编程
- 三角函数在前端动画中的应用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
YC创业营: 硅谷顶级创业孵化器如何改变世界
兰德尔·斯特罗斯 (Randall Stross) / 苏健 / 浙江人民出版社 / 2014-8-1 / CNY 52.90
在互联网创业成本日益降低、融资却越来越难的今天,硅谷的Y Combinator因何成为全世界创业者趋之若鹜的创业圣地?为什么25岁左右的青年最适合创业?创业者如何才能在遴选面试中脱颖而出?为什么YC特别看好那些主要由黑客组成的创业团队? YC真的歧视女性吗?如何想出能够赢得投资的新点子?创业者应该如何寻找联合创始人? 获准进入Y Combinator及其创业公司全程跟踪批量投资项目的第一人,......一起来看看 《YC创业营: 硅谷顶级创业孵化器如何改变世界》 这本书的介绍吧!