防抖
<body>
<!-- 防抖和节流:限制函数的执行次数
1.防抖:通过setTimeout的方式,在一定时间间隔内,将多次触发变成一次触发
2.节流:减少一段时间的触发频率
-->
<input type="text">
<input type="text" id="input">
<script>
var btn = document.getElementById('input')
btn.addEventListener('click', debounce(submit, 2000, true),false)
// btn.addEventListener('click', submit,false)
//submit没有被debounce包装时,可以通过this、e来指向btn和属性
function submit(e){
// console.log(this);
// console.log(e);
console.log(1);
}
// 11.完成上述步骤后会出现一个问题是你第一次点击的时候也会有很明显的延时,
// 你不妨将代码中的timer换成你想要的数字试一试,比如3000
// 12.这里定义了一个triggleNow作为标识,
// 希望你在第一次点击并且它为真时能够直接去执行这个函数,不去走setTimeout函数
function debounce(fn, timer, triggleNow){
var t= null; // 2.初始化一个t为空
// 1. 因为windows调用debounce函数时中传入了一个参数(submit)是函数
// 1.所以windows应该执行的是应该是该函数返回的函数
return function(e){
// 5.被debounce包装时,win在调用函数时传进来的实参可以在这里被拿到
console.log(e)
// 6.arguments是实参列表,第0项时会获取到事件参数,是我们想获取的事件对象,但这个arguments不能直接传到计时器里的fn()中
// 因为只有函数内部才会存在arguments,在setTimeout中打印arguments对应的是该函数内部的参数
console.log(arguments[0])
// 9.这里的this指向为btn
console.log(this);
if(t){
// 3. 如果t存在则清空计时器t
clearTimeout(t)
}
if(triggleNow){
var firstClick = !t
if(firstClick){
fn.apply(this,arguments);
}
t = setTimeout(()=>{
t = null;
}, timer)
} else {
t = setTimeout(()=>{
fn.apply(this,arguments);
}, timer)
}
// 1.延时
// 1. 使用setTimeout限制fn的执行
// 4. t不存在时重新声明一个计时器,重新计时
// 7.为了解决6中的问题,我们使用箭头函数(箭头函数内部没有arguments对象),
// 将arguments指向外部的函数(此函数的上一层函数)的参数
// t = setTimeout(()=>{
// 8.使用apply方法绑定this指向,让arguments作为第二个参数传入fn
// 10.这里的this指向的外部函数(此函数的上一层函数)的this
// fn.apply(this,arguments);
// }, timer)
}
}
</script>
</body>
第一次点击无延时的简化的代码:
<input type="text">
<input type="text" id="input">
<script>
var btn = document.getElementById('input')
btn.addEventListener('click', debounce(submit, 2000, true),false)
function submit(e){
console.log(1);
}
function debounce(fn, timer, triggleNow){
var t= null;
return function(e){
if(t){
clearTimeout(t)
}
var firstClick = !t
if(firstClick){
fn.apply(this,arguments);
}
t = setTimeout(()=>{
t = null;
}, timer)
}
}
</script>
节流
<body>
<input type="text">
<input type="text" id="input">
<script>
var btn = document.getElementById('input')
btn.addEventListener('click', throttle(submit, 2000),false)
function submit(e){
console.log(e,this);
}
function throttle(fn, delay){
var begin = 0
return function(){
var cur = new Date().getTime();
if( cur -begin > delay){
fn.apply(this,arguments);
begin = cur;
}
}
}
</script>
</body>
性能优化面试题链接
前端性能优化篇