- 函数防抖
频繁触发情况下, 一段时间内只会执行一次
应用场景:
表单元素的校验,如手机号,邮箱,用户名等,部分搜索功能的模糊查询结果实现
<!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>防抖</title>
</head>
<body>
<input id="ipt" type="text" />
<script>
let ipt = document.getElementById("ipt");
// 防抖: 频繁触发情况下, 一段时间内只会执行一次
// 应用场景: 表单元素的校验,如手机号,邮箱,用户名等,部分搜索功能的模糊查询结果实现
function _debounce(fn, delay) {
// 指定默认值: 时间间隔
delay = delay || 1000;
let timer = null;
return function () {
// 考虑作用域,上下文环境,apply 需要用到 this 对象
let th = this;
// 接收的参数用 ES6 中的 rest 参数统一存储到变量 args 中。arguments 就是传入的参数数组, 而且个数可以不确定的传回给 fn (不确定函数到底有多少个参数,用 arguments 来接收)
let args = arguments
// 判断定时器是否存在,清除定时器
timer && clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(th, args)
timer = null;
}, delay)
}
}
ipt.addEventListener('keyup', _debounce(function inputChange(e) {
console.log(e.target.value);
}))
</script>
</body>
</html>
- 函数节流
频繁触发情况下, 时间间隔内只执行一次
应用场景:
鼠标的跟随动画实现,scroll,resize, touchmove, mousemove等极易持续性促发事件的相关动画问题,降低频率
<!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>节流</title>
<style>
#container {
width: 100px;
height: 100px;
background-color: #3496db;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
let container = document.getElementById("container");
// 节流: 频繁触发情况下, 时间间隔内只执行一次
// 应用场景: 鼠标的跟随动画实现,scroll,resize, touchmove, mousemove等极易持续性促发事件的相关动画问题,降低频率
// 时间戳方式
function _throttle(fn, interval) {
// last为上一次触发回调的时间
let last = 0;
interval = interval || 1000;
return function () {
// 考虑作用域,上下文环境,apply 需要用到 this 对象
let th = this;
// 接收的参数用 ES6 中的 rest 参数统一存储到变量 args 中。arguments 就是传入的参数数组, 而且个数可以不确定的传回给 fn (不确定函数到底有多少个参数,用 arguments 来接收)
let args = arguments;
// 记录本次触发回调的时间
let now = Date.now();
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= interval) {
fn.apply(th, args);
last = now;
}
}
}
// 定时器方式
function _throttleD(fn, delay) {
let sign = true;
delay = delay || 1000;
return function () {
// 考虑作用域,上下文环境,apply 需要用到 this 对象
let th = this;
// 接收的参数用 ES6 中的 rest 参数统一存储到变量 args 中。arguments 就是传入的参数数组, 而且个数可以不确定的传回给 fn (不确定函数到底有多少个参数,用 arguments 来接收)
let args = arguments;
// 在函数开头判断标志是否为 true,不为 true 则中断函数
if (!sign) return;
// sign 设置为 false,防止执行之前再被执行
sign = false;
setTimeout(() => {
fn.apply(th, args);
// 执行完事件之后,重新将这个标志设置为 true
sign = true;
}, delay);
}
}
container.addEventListener('mousemove', _throttleD(function (e) {
console.log(e.pageX)
}))
</script>
</body>
</html>
- 总结
函数防抖与节流的异同点
相同点:
防抖和节流都是防止某一时间频繁触发, 但原理不一样;
区别:
函数防抖是某一段时间内只执行一次
函数节流是间隔时间执行