JS - 函数防抖详解
目录
- 一、使用场景
- 二、实现思路(详解,es6之前版本)
- 三、es6实现
- 四、第三方库
一、使用场景
- 函数内执行耗时操作
- 函数执行不频繁,只有最后一次有意义
- 举例:鼠标移动事件,键盘输入事件…等需要逻辑处理时
二、实现思路(详解,es6之前版本)
举例场景为键盘输入事件,函数内部通过apply改变this指向,通过slice处理arguments(参数集)伪数组
- 前置
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>函数防抖</title>
</head>
<body><input type="text">
</body>
<script>var input = document.querySelector('input');input.addEventListener('input', function(e) {console.log(e.target.value);});
</script>
</html>
- 实现延时触发效果 – 使用高阶函数思想封装函数
高阶函数(至少满足以下条件之一)
:1.接受一个或多个函数作为参数。2.返回一个新的函数。
function debounce(fn, delay) {return function() {setTimeout(() => {fn();}, delay);}}var newFn = debounce(function() {console.log(111);}, 1000);var input = document.querySelector('input');input.addEventListener('input', newFn);
- 实现只响应最后一次触发 – 利用setTimeout返回值进行处理
这里将this改为打印内容,我们可以发现this为undefined。
原因:函数的this指向调用者,那么当前fn是在setTimeout中调用,指向全局
function debounce(fn, delay) {var timer = null;return function() {clearTimeout(timer);timer = setTimeout(() => {fn();}, delay);}}var newFn = debounce(function() {console.log(this);}, 1000);var input = document.querySelector('input');input.addEventListener('input', newFn);
- 实现this绑定和参数传递
arguments:函数调用时传入的所有参数(伪数组)
function debounce(fn, delay) {var timer = null;return function() {clearTimeout(timer);timer = setTimeout(() => {var args = Array.prototype.slice.call(arguments,0); // 伪数组转化fn.apply(this,args);}, delay);}}var newFn = debounce(function(e) {console.log(this.value,e);}, 1000);var input = document.querySelector('input');input.addEventListener('input', newFn);
- 自定义参数传递
function debounce(fn, delay) {var timer = null;return function() {clearTimeout(timer);timer = setTimeout(() => {var args = Array.prototype.slice.call(arguments,0);fn.apply(this,args);}, delay);}}var newFn = debounce(function(e,a) {console.log(e,a);}, 1000);var input = document.querySelector('input');input.addEventListener('input', (e)=>{newFn(e,1);});
三、es6实现
使用箭头函数、解构赋值、剩余参数等现代 JavaScript 特性
!!!箭头函数没有自己的 this,它会继承定义时所在作用域的 this
const debounce = (fn, delay) => {let timer = null;return function(...args) {clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args);}, delay);}}const newFn = debounce(function(e) {console.log(e, this.value);}, 1000);const input = document.querySelector('input');input.addEventListener('input', newFn);
四、第三方库
lodash中文官网