我們知道,js有些事件例如resize,mousemove等是會不間斷觸發(fā)的,例如我們簡單的一個scroll事件:
function scrollFn() {
console.log(1)
}
window.onscroll = scrollFn
我們需要在滾動的時候去做一些事情,如上圖可見,我們只是簡單的console,在一次滾動過程中函數(shù)即執(zhí)行了將近20次,如果這個函數(shù)有更為復雜的方法,比如操作dom或者其他交互,會嚴重影響性能。
為了避免這個問題,我們一般會使用定時器來對函數(shù)進行節(jié)流。
在javascript高級程序設計中,定義了一個函數(shù)節(jié)流方法,如下:
function throttle(method,context) { // 執(zhí)行函數(shù)、哪個作用域中執(zhí)行
clearTimeout(method.tId);
method.tId = setTimeout(function() {
method.call(context)
},300)
}
throttle函數(shù)接收兩個參數(shù),即要執(zhí)行的函數(shù)及執(zhí)行環(huán)境,如果執(zhí)行環(huán)境未定義,默認則為windows。在這個函數(shù)中,會在第一次執(zhí)行時為method一個定時器屬性,在指定時間間隔(300)內(nèi)再次執(zhí)行時會清楚上一次定義的定時器并創(chuàng)建新定時器知道停止。
函數(shù)節(jié)流
函數(shù)預先設定一個執(zhí)行周期,當調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進入下一個新周期。
function throttle(method, duration) {
let begin = new Date()
return function () {
const context = this, args = arguments
let current = new Date()
if (current - begin >= duration) {
method.apply(context, args)
begin = current
}
}
}
function resize() {
let n = 1
console.log(++n)
}
window.onresize = throttle(resize, 5000)
函數(shù)防抖
函數(shù)調(diào)用n秒后才會執(zhí)行,如果函數(shù)在n秒內(nèi)被調(diào)用的話則函數(shù)不執(zhí)行,重新計算執(zhí)行時間。
function debounce(method, delay) {
let timer = null
return function () {
const context = this, args = arguments
clearTimeout(timer)
timer = setTimeout(function () {
method.apply(context, args)
}, delay)
}
}
function resize() {
let n = 1
console.log(++n)
}
window.onresize = debounce(resize, 500)