防抖(debounce):对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是规定事件发生的n毫秒后再执行,如果n毫秒内事件再次被触发,则定时器重新开始计时,直至定时器倒计时结束。
效果:如果短时间内大量触发同一事件,只会执行一次函数。
节流(throttle):如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
栗子1.function版本防抖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>input 搜索防抖测试</title>
</head>
<body>
<input id='input1' />
<script>
// 用request 模拟异步请求
var request = (data) => {
setTimeout(() => console.log('receive', data))
}
function debounce(fn, delay) {
var priorId = null;
console.log('debounce', this)
return function() {
if(priorId !== null) {
clearTimeout(priorId)
}
console.log('return function this', this)
priorId = setTimeout(fn, delay)
}
}
var input = document.getElementById('input1');
// 添加事件监听
input.addEventListener('input', debounce(handleInput, 2000))
function handleInput(event) {
console.log('handleInput', event, this);
data = document.getElementById('input1').value;
request(data)
}
</script>
</body>
</html>
控制台打印
函数直接被调用时,this绑定的是全局对象,浏览器中是window.而且在setTimeout函数里,传入的函数,this也会默认指向window.所以handleInput里面,this指向window.
让handleInput正确拿到this解决方法:在setTimeout里面给通过apply把this绑定,只改变debounce
function debounce(fn, delay) {
var priorId = null;
console.log('debounce', this)
return function() {
if(priorId !== null) {
clearTimeout(priorId)
}
console.log('return function this', this)
// 将arguments向下传递给fn
priorId = setTimeout(() => fn.apply(this, arguments), delay)
}
}
防抖函数传参,主要是使用apply或cal,apply传递的参数是参数数组或arguments;call传递的是逐个列举的参数进行.
栗子2.箭头函数版防抖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>箭头函数版防抖</title>
</head>
<body>
<input id='input1' />
<script>
var request = (data) => {
setTimeout(() => console.log(data))
}
var handleInput = (event) => {
//console.log('handleinput',event)
request(event.target.value)
}
var debounce = (fn) => {
var priodid = null
return (args) => {
if(priodid !== null) {
clearTimeout(priodid)
}
priodid = setTimeout(() => fn.call(this, args), 2000) ;//箭头函数call只是用于传参
}
}
var input = document.getElementById('input1');
input.addEventListener('input', debounce(handleInput))
</script>
</body>
</html>