JavaScript 函数防抖

<!DOCTYPE html>
<html lang="zh-cmn-Hans">

<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container{
100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
}
</style>
</head>

<body>
<div id="container"></div>
<script src="debounce.js"></script>
</body>

</html>

debounce.js 文件的代码如下:

var count = 1;
var container = document.getElementById('container');

function getUserAction() {
container.innerHTML = count++;
};


container.onmousemove = getUserAction;

触发事件,但是我一定在事件触发 n 秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,那我就以新的事件的时间为准,n 秒后才执行,总之,就是要等你触发完事件 n 秒内不再触发事件,

// 第一版
function debounce(func, wait) {
var timeout;
return function () {
clearTimeout(timeout)
timeout = setTimeout(func, wait);
}
}

container.onmousemove = debounce(getUserAction, 1000);

如果我们在 getUserAction 函数中 console.log(this),在不使用 debounce 函数的时候,this 的值为:

<div id="container"></div>

但是如果使用我们的 debounce 函数,this 就会指向 Window 对象!

所以我们需要将 this 指向正确的对象。

// 第二版
function debounce(func, wait) {
var timeout;

return function () {
var context = this;

clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context)
}, wait);
}
}

event 对象

JavaScript 在事件处理函数中会提供事件对象 event,我们修改下 getUserAction 函数:

function getUserAction(e) {
console.log(e);
container.innerHTML = count++;
};

JavaScript 在事件处理函数中会提供事件对象 event,我们修改下 getUserAction 函数:

function getUserAction(e) {
console.log(e);
container.innerHTML = count++;
};

// 第三版
function debounce(func, wait) {
var timeout;

return function () {
var context = this;
var args = arguments;

clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}

返回值

// 第四版
function debounce(func, wait) {
var timeout, result;

return function () {
var context = this;
var args = arguments;

clearTimeout(timeout)
timeout = setTimeout(function(){
result = func.apply(context, args)
}, wait);

return result;
}
}

我们修复了三个小问题:

  1. this 指向
  2. event 对象
  3. 返回值

立刻执行

我不希望非要等到事件停止触发后才执行,我希望立刻执行函数,然后等到停止触发n秒后,才可以重新触发执行。

// 第五版
function debounce(func, wait, immediate) {

var timeout, result;

return function () {
var context = this;
var args = arguments;

if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) result = func.apply(context, args)
}
else {
timeout = setTimeout(function(){
result = func.apply(context, args)
}, wait);
}

return result;
}
}

取消

// 第六版
function debounce(func, wait, immediate) {

var timeout, result;

var debounced = function () {
var context = this;
var args = arguments;

if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) result = func.apply(context, args)
}
else {
timeout = setTimeout(function(){
result = func.apply(context, args)
}, wait);
}
return result;
};

debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};

return debounced;
}

原文地址:https://www.cnblogs.com/zhouyideboke/p/9876713.html