<!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{
width: 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;
}
我們修複了三個小問題:
- this 指向
- event 對象
- 傳回值
立刻執行
我不希望非要等到事件停止觸發後才執行,我希望立刻執行函數,然後等到停止觸發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;
}