浅谈JS函数防抖及应用场景
【前言】
在工作中,我们可能碰到这样的问题:
- 用户在搜索的时候,在不停敲字,如果每敲一个字我们就要调一次接口,接口调用太频繁,给卡住了。
- 用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每滚动一下就监听,那样会太过频繁从而占内存,如果再加上其他的业务代码,就卡住了。
所以,这时候,我们就要用到 防抖与节流 了。
那么,讲到 防抖与节流,我们可以顺带探秘下 重绘与回流。
说起 重绘与回流,我们就顺带把 浏览器输入 URL 后发生的事情 也关注一下,从而引出 DNS、TCP 等知识点,最终串起来构成本文的轮廓,方便 jsliang 和小伙伴们对这块知识的整理与记忆。
【主体】
本节主要介绍函数防抖debounce
下面我们有段防抖小案例代码。
如果小伙伴们手头有电脑,并感兴趣想先自己思考下什么是防抖。可以将代码复制到浏览器,尝试点击按钮,并关注下控制台,看看 Console 是如何打印的。
如果小伙伴们手头没有电脑,那么咱一起先瞅瞅代码实现,再看看下面 GIF 演示。(这样效果没有自己敲的直白有效)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>防抖</title> </head> <body> <button id="debounce">点我防抖!</button> <script> window.onload = function() { // 1、获取这个按钮,并绑定事件 var myDebounce = document.getElementById("debounce"); myDebounce.addEventListener("click", debounce(sayDebounce)); } // 2、防抖功能函数,接受传参 function debounce(fn) { // 4、创建一个标记用来存放定时器的返回值 let timeout = null; return function() { // 5、每次当用户点击/输入的时候,把前一个定时器清除 clearTimeout(timeout); // 6、然后创建一个新的 setTimeout, // 这样就能保证点击按钮后的 interval 间隔内 // 如果用户还点击了的话,就不会执行 fn 函数 timeout = setTimeout(() => { fn.call(this, arguments); }, 1000); }; } // 3、需要进行防抖的事件处理 function sayDebounce() { // ... 有些需要防抖的工作,在这里执行 console.log("防抖成功!"); } </script> </body> </html>
很好,相信小伙伴们已经看完了代码,下面我们看看它的演示:
这时候,我们可以抛出防抖的概念了:
- 防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
结合上面的代码,我们可以了解到,在触发点击事件后,如果用户再次点击了,我们会清空之前的定时器,重新生成一个定时器。意思就是:这件事儿需要等待,如果你反复催促,我就重新计时!
空讲无益,show you 场景:
- 有个输入框,输入之后会调用接口,获取联想词。但是,因为频繁调用接口不太好,所以我们在代码中使用防抖功能,只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。
小伙伴们可以尝试看着上面的案例,先自己实现一遍这个场景的解决,如果感觉不行,那就看:《防抖和节流的应用场景和实现》
知识点补充:何为
arguments?
首先,后端转前端的同学,可以将arguments理解为能实现重载函数功能的工具。
然后,我们举个例子:在function test()这个方法中,由于我们不确定变量有多少,比如test("jsliang", 24),又或者test("LiangJunrong", "jsliang", "24"),这时候只需要在函数test中用arguments接收就行了。
最后,在function test() { let arr1 = argument[0] }中,arr1就可以获取到传进来的第一个变量。
所以,fn.call(this, arguments)其实是将不确定变量替换到函数中了。
参考资料 1:《闲聊 JS 中的 apply 和 call》
参考资料 2:《js 中 arguments 的用法》
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<input type="text" name="search">
<script type="text/javascript">
var searchInput = document.querySelector('input[name="search"]');
/*绑定事件*/
searchInput.addEventListener('keyup',debounce(getInputValue),false);
/* 防抖函数 */
function debounce(fn){
var timer = null;
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.call(this,arguments)
},500)
}
}
/* 调用获取输入值 */
function getInputValue(){
console.dir(this.value)
}
</script>
</body>
</html>
.

浙公网安备 33010602011771号