节流和防抖都是不希望事件被一直频繁地触发。
防抖:在事件一直被触发的过程中不会触发,当事件停止触发的一段时间后才会被触发,例如技能释放需要蓄力,当蓄力过程中被打断(再次点击了技能),蓄力值清空需要重新蓄力。
节流:规定的时间段内只触发一次,例如fps游戏中的射击,一直点着开枪,只会在射速时间内发射一枚子弹。(可以分为第一次马上触发和第一次按规定时间触发)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
正常输入输入一次触发一次<br><input id="normal" type="text"><br><br>
有防抖,输入停止之后的1秒后再触发<br><input id="debounce" type="text"><br><br>
节流,规定时间内只触发一次(分为第一次会触发、和不会触发的情况)<br><input id="throttle" type="text"><br><br>
</body>
<script>
// 模拟 ajax 请求
function ajax(e) {
console.log(e.target.value)
}
// 防抖函数debounce
function debounce(fn, time) {
let timeout = null
return function(...args) {
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.call(this, ...args)
}, time)
}
}
// 封装节流函数
function throttle(fn, time) {
// 第一次按时间触发
// let flag = null
// return function(...args) {
// if (!flag) {
// flag = setTimeout(() => {
// fn.call(this, ...args)
// flag = null
// }, time)
// }
// }
// 第一次立即会触发
let pre = 0;
return function(...args){
let now = Date.now();
if( now - pre >= time){
fn.call(this, ...args);
pre = Date.now();
}
}
}
let inputa = document.getElementById('normal')
let inputb = document.getElementById('debounce')
let inputc = document.getElementById('throttle')
inputa.oninput = function(e) {
ajax(e)
}
inputb.oninput = debounce(function(e) {
ajax(e)
},1000)
inputc.oninput = throttle(function(e) {
ajax(e)
},1000)
</script>
<style>
.flex {
}
</style>
</html>
q1: argument有什么用?
q2: 为什么要用call或是apply,而不直接调用?
q3: 节流防抖分别应用在什么地方?