共计 3027 个字符,预计需要花费 8 分钟才能阅读完成。
面试一面大概率问题:
- 什么是防抖,如何防抖?
- 什么是节流,如何节流?
一 目录
不折腾的前端,和咸鱼有什么区别
目录 |
---|
一 目录 |
二 防抖 |
2.1 手写防抖 |
2.2 防抖利用 |
三 节流 |
3.1 手写节流 |
3.2 节流利用 |
四 防抖 + 节流 |
二 防抖
返回目录
防抖 :工作频繁触发的状况下,只有工作触发的距离超过指定距离的时候,工作才会执行。
举例:
- 监听拖拽滚动条,而后频繁向下滚动信息,会变得很慢,很机灵。
- 点击提交表单后,用户在后果还没进去的时候反复触发。
简略来说:某件事你并不想它太过频繁触发,那么设置一个定时器,每次进来的时候都革除本来的定时器,而后从新开始计时。
2.1 手写防抖
返回目录
- 设置定时器
- 设置一个闭包,返回一个办法
- 如果重复进来,清空后面的定时器,再从新设置一遍
function debounce(fn) { | |
let timer = null; | |
return function() {clearTimeout(timer); | |
timer = setTimeout(() => {fn.call(this.arguments); | |
}, 1000); | |
} | |
} |
2.2 防抖利用
返回目录
联合实例:
<!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,// 这样就能保障点击按钮后的 1000 毫秒距离内 | |
// 如果用户还点击了的话,就不会执行 fn 函数 | |
timeout = setTimeout(() => {fn.call(this, arguments); // 修改 this 指向问题 | |
}, 1000); | |
}; | |
} | |
// 3、须要进行防抖的事件处理 | |
function sayDebounce() {console.log(this); | |
// ... 有些须要防抖的工作,在这里执行 | |
console.log("防抖胜利!"); | |
} | |
</script> | |
</body> | |
</html> |
三 节流
返回目录
节流 :指定工夫距离内只会执行一次工作。
举例:
- 你不想频繁为你女票买单,于是约好每月 1 号清空购物车
- 避免过快拖动滚动条,导致 JS 跟不上拖动频率,通过节流限度每秒触发监听的次数(固定工夫固定频率)
简略来说:年轻人要放弃一日三餐,法则作息,那就通过节流来限度。
3.1 手写节流
返回目录
- 设置一个标记
- 设置一个闭包,返回一个办法
- 如果反复进去的时候,标记曾经动了,那就组织程序进一步运行
- 如果定时器执行完了,设置这个标记为没动,容许下一次执行
function throttle(fn) { | |
let timer = true; | |
return function() {if (!timer) {return;} | |
timer = false; | |
setTimeout(() => {fn.call(this, arguments); | |
timer = true; | |
}, 1000); | |
} | |
} |
3.2 节流利用
返回目录
联合实例:
<!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="throttle"> 点我节流!</button> | |
<script> | |
window.onload = function() { | |
// 1、获取按钮,绑定点击事件 | |
var myThrottle = document.getElementById("throttle"); | |
myThrottle.addEventListener("click", throttle(sayThrottle)); | |
} | |
// 2、节流函数体 | |
function throttle(fn) { | |
// 4、通过闭包保留一个标记 | |
let canRun = true; | |
return function() { | |
// 5、在函数结尾判断标记是否为 true,不为 true 则中断函数 | |
if(!canRun) {return;} | |
// 6、将 canRun 设置为 false,避免执行之前再被执行 | |
canRun = false; | |
// 7、定时器 | |
setTimeout(() => {fn.call(this, arguments); | |
// 8、执行完事件(比方调用完接口)之后,从新将这个标记设置为 true | |
canRun = true; | |
}, 1000); | |
}; | |
} | |
// 3、须要节流的事件 | |
function sayThrottle() {console.log("节流胜利!"); | |
} | |
</script> | |
</body> | |
</html> |
四 防抖 + 节流
返回目录
防抖有时候因为触发太过频繁,导致一次响应都没有。
所以心愿固定的工夫必然给用户一个响应,于是就有了防抖 + 节流的操作。
- 设置
last
记录定时器开始的工夫 - 设置
timer
示意一个定时器 - 获取以后工夫
now
- 如果以后工夫 – 开始工夫小于延迟时间,那么就防抖
- 否则设置工夫到了,执行函数
function throttle(fn, delay) { | |
let last = 0, timer = null; | |
return function (...args) {let now = new Date(); | |
if (now - last < delay){clearTimeout(timer); | |
setTimeout(function() { | |
last = now; | |
fn.apply(this, args); | |
}, delay); | |
} else { | |
// 这个时候示意工夫到了,必须给响应 | |
last = now; | |
fn.apply(this, args); | |
} | |
} | |
} |
jsliang 的文档库由 梁峻荣 采纳 常识共享 署名 - 非商业性应用 - 雷同形式共享 4.0 国内 许可协定 进行许可。<br/> 基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/> 本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。
正文完