函数内返回函数的特点
函数返回另一个函数(当前声明)是高级函数的用法,原理还来不及细究,但特点是,我们第一次调用只是构建了一个外层函数体对象,只有有后续的调用,才能调用内层函数体,并且重复调用,只会重复内层函数体。
而如果在一个函数内返回的是一个已经声明的函数,其实是调用已经声明的函数,跟上面的情况是不一样的,不存在函数内return返回函数的特点。
防抖节流实现代码
看了很多防抖节流的代码,好多都测试不成功,看逻辑也不是太合理,下面是亲测成功的实现防抖节流的方法,用到了函数体内返回一个当前声明的函数:
<body>
<div>
<button id="debounce">防抖</button>
<button id="throttle">节流</button>
</div>
<script type="text/javascript">
//真实要执行的函数
function submit(){
console.log("防抖和节流");
console.log(this)
}
//防抖函数
function debounce(fn,delay){
//设置time为定时器
let time = null; // 第一次调用此函数时执行,重复调用函数只执行return的函数
//闭包原理,返回一个函数
return function (){
//如果定时器存在则清空定时器(定时器时间到了执行完了就不存在了)
if(time){
clearTimeout(time);
}
//设置定时器,规定时间后执行真实要执行的函数
time = setTimeout(() => {//此箭头函数里的this指向button这个按钮
// 改变真实要执行函数的this指向,
// 原fn(即submit函数)里面的this指向window,
// 现在fn里面的this指向此箭头函数里的this,也就是button按钮
fn.call(this);
},delay);
}
}
//节流函数
function throttle (fn,delay) {
let bef = 0; // 第一次调用此函数时执行,重复调用函数只执行return的函数
return function (){
//获取当前时间戳
let now = new Date().getTime();
//如果当前时间减去上次时间大于限制时间时才执行
if(now - bef > delay){
fn.call(this);
bef = now;
}
}
}
// 绑定事件
document.querySelector("#debounce").addEventListener("click", debounce(submit,1000))
document.querySelector("#throttle").addEventListener("click", throttle(submit,1000))
</script>
</body>
防抖节流使用场景
一般提交表单时使用防抖,但在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。