「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
防抖
背景
我们在平时开发的时候,会有很多场景会频繁触发事件,比如说input框的input事件,搜索框实时发请求,resize,onscroll,onmousemove等等,有些时候,我们并不能或者不想频繁触发事件,那怎么办呢?这时候就应该用到函数防抖和函数节流了。
定义
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
生活中的例子:如果有人进电梯(触发事件),那电梯将在10秒后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
本质:防抖动是将多次执行变为最后一次执行
用法和使用场景
思路:每次触发事件时都取消之前的延时调用方法
可以应用在输入框搜索,控制调用接口的频率。也可以用来监听窗口的变化。
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function() {
// 每当用户输入的时候把前一个setTimeout clear掉
clearTimeout(timeout);
// 然后又创建一个新的setTimeout,
// 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行fn函数
timeout = setTimeout(() => {
// 关键在第一个参数,为了确保上下文环境为当前的this,所以不能直接用fn
fn.apply(this, arguments);
}, 500);
}
}
function sayHi() {
console.log('防抖成功');
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖
二、节流
背景
我们在平时开发的时候,会有很多场景会频繁触发事件,比如说input框的input事件,搜索框实时发请求,resize,onscroll,onmousemove等等,有些时候,我们并不能或者不想频繁触发事件,那怎么办呢?这时候就应该用到函数防抖和函数节流了。
定义
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
本质:节流是将多次执行变为每隔一段时间执行
用法和使用场景
思路:每次触发事件时都判断当前是否有等待执行的延时函数 可以应用在监听滚动条的位置,或者频繁点击按钮的优化。
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function() {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true,则return
canRun = false;
setTimeout(() => {
fn.apply(this, arguments); //关键在第一个参数,为了确保上下文环境为当前的this,所以不能直接用fn。
// 最后在setTimeout执行完毕后再把标记设置为true
// (关键)表示可以执行下一次循环了。
// 当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500)
}
}
function sayHi(e) {
console.log(e.target.innerWith, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi)); // 节流
三、防抖和节流的区别
防抖:动作绑定事件,动作发生后一定时间后触发事件,在这段时间内,如果该动作又发生,则重新等待一 定时间再触发事件。
节流:动作绑定事件,动作发生后一段时间后触发事件,在这段时间内,如果动作又发生,则无视该动作,直到事件执行完后,才能重新触发。
// 防抖的实现
function debounce(func, time) {
let timer = null;
return () => {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, arguments);
}, time);
}
}
// 节流的实现
function throtte(func, time) {
let activeTime = 0;
return () => {
const current = Date.now();
if (current - activeTime > time) {
func.apply(this, arguments);
activeTime = Date.now();
}
}
}
JQuery的ready函数与JS的onload的区别:
1)执行时间:
window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行;
$(document).ready()是Dom结构绘制完毕后就执行,不必等到加载完毕。
2)编写个数不同:
window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个;
$(document).ready()可以同时编写多个,并且都可以得到执行。