一.防抖之前端人话
防抖, 简而言之就是window 中的 resize、scroll, mousedown、mousemove, keyup、keydown等事件频繁的发生, 如果这些事件处理函数有异步方法,容易造成页面的卡顿, 解决的方法之一就是防抖(debounce), 其二是节流(throtter).
防抖和节流到底啥区别: 防抖是事件持续触发,等待事件停止触发后n才执行函数. 节流是事件持续触发的时候,每n秒执行一次函数
function debounce(func, wait) {
let timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(func, wait);
}
}
一.func方法中的this和event对象
上面方法中的this是指向window, 如何将this指向当前的作用的对象, 如何获取event对象
function debounce(func, wait) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args)
}, wait);
}
}
二.不希望等到n秒后才执行,希望立即执行, 等到停止触发n秒后才可以重新执行, 如何做 ?
function debounce(func, wait, immediate) {
let timeout;
return function() {
const context = this;
const args = arguments;
if(timeout) {
clearTimeout(timeout);
}
if(immediate) {
// 如果执行过,不再执行
const callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait);
if(callNow) {
func.apply(context, args);
}
} else {
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
}
}
}
三.如何返回func函数的返回值?
只有当immediate为true的时候才将func的结果返回, 因为immediate为false的时候, 我们将执行函数放在定时器中,返回结果永远是undefined
function debounce(func, wait, immediate) {
let timeout;
let result;
return function() {
const context = this;
const args = arguments;
if(timeout) {
clearTimeout(timeout);
}
if(immediate) {
// 如果执行过,不再执行
const callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait);
if(callNow) {
result = func.apply(context, args);
}
} else {
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
}
return result;
}
}
四.如何取消debounce函数, eg:debounce间隔是10秒,立即执行, 我只能等到10秒后才能触发执行, 这时候希望有一个按钮, 点击可以取消防抖, 这样再去触发,就可以立即执行, 如何做 ?
function debounce(func, wait, immediate) {
let timeout;
let result;
const debouned = function() {
const context = this;
const args = arguments;
if(timeout) {
clearTimeout(timeout);
}
if(immediate) {
// 如果执行过,不再执行
const callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait);
if(callNow) {
result = func.apply(context, args);
}
} else {
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
}
return result;
}
debouned.cancel = function() {
clearTimeout(timeout);
timeout = null;
}
return debouned;
}
二.节流
一. 时间戳实现
- 鼠标第一次移入的时候会立刻执行
- 事件停止触发后没有办法再执行 ```javascript
function throttle(func, wait) { let previous = 0 let context let args
return function() { let now = +new Date() context = this args = arguments
if (now - previous > wait) {
func.apply(context, args)
previous = now
}
} }
<a name="0LmuN"></a>
### 二. 定时器实现
1. 不会立即执行, n秒后第一次执行
1. 停止触发后依然会再执行一次
```javascript
function throttle2(func, wait) {
let timeout
return function() {
let context = this
let args = arguments
if(!timeout) {
timeout = setTimeout(function(){
timeout = null
func.apply(context, args)
}, wait)
}
}
}