函数防抖和节流 什么是函数防抖? 短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行
而我们的函数防抖分为立即执行版和非立即执行版:
非立即执行版: 1 2 3 4 5 6 7 8 9 10 11 function debounce (func, wait ) { let timeout; return function ( ) { const context = this ; const args = [...arguments ]; if (timeout) clearTimeout (timeout); timeout = setTimeout (() => { func.apply (context, args) }, wait); } }
非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
立即执行版: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function debounce (func, wait ) { let timer; return function ( ) { let context = this ; let args = arguments ; if (timer) clearTimeout (timer); let callNow = !timer; timer = setTimeout (() => { timer = null ; }, wait) if (callNow) func.apply (context, args); } }
立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果
合成版: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function debounce (func, wait, immediate ) { let timeout = null , result = null return function (...args ) { let now = immediate && !timeout if (timeout)clearTimeout (timeout) timeout = setTimeout (() => { if (!immediate) result = func.call (this , ...args) timeout = null },wait) if (now) result = func.call (this , ...args) return result } }
我们常见的工具库, 比如说lodash中就对我们的这个函数防抖做了一个封装, 如果我们的在工作中遇到类似的需求, 就可以直接自己写一个或者是用人家的
函数防抖的主要使用场景: 函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:
搜索框搜索输入。只需用户最后一次输入完,再发送请求;
用户名、手机号、邮箱输入验证;
浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。
函数节流: 限制一个函数在一定时间内只能执行一次
主要实现思路就是通过 setTimeout 定时器,通过设置延时时间,在第一次调用时,创建定时器,先设定一个变量,然后把定时器赋值给这个变量,再写入需要执行的函数。第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为false。那么下次判断变量时则为false,函数会依次运行。目的在于在一定的时间内,保证多次函数的请求只执行最后一次调用
节流也是有下面几个版本:
时间戳版本:函数立即执行,间隔wait秒
定时器版本:间隔wait秒,函数执行,结束后函数在执行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 function throttle (fn, wait ) { let result = null , per = null return function (...args ) { let now = new Date if (now - per > wait) { result = fn.call (this , ...args) per = now } return result } } function throttle (fn, wait ) { let timerout = null return function (...args ) { if (!timerout) { timerout = setTimeout (() => { fn.call (this , ...args) clearTimeout (timerout) timerout = null }, wait); } } } function throttle (fn, wait ) { let result = null , timerout = null , pre = null return function (...args ) { let now = new Date remaining = wait - (now - pre) if (remaining <= 0 ) { pre = now clearTimeout (timerout) timerout = null result = fn.call (this , ...args) } else if (!timerout) { timerout = setTimeout (() => { pre = new Date timerout = null result = fn.call (this , ...args) }, remaining); } return result } }
使用场景:
懒加载、滚动加载、加载更多或监听滚动条位置;
百度搜索框,搜索联想功能;
防止高频点击提交,防止表单重复提交;