自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

再也不怕面試官問我防抖與節(jié)流了

開發(fā) 后端
防抖就是要延遲執(zhí)行,你一直操作觸發(fā)事件一直不執(zhí)行,當你停止操作等待多少秒后才執(zhí)行,節(jié)流顧名思義,一節(jié)一節(jié)的流,就好似控制水閥,在事件不斷觸發(fā)的過程中,固定時間內(nèi)執(zhí)行一次事件。

最近去面試,又遇到面試官問我防抖與節(jié)流了,而明明前幾天就看過手寫代碼,卻寫不出來。有時候我在想,是不是自己太笨了。

回歸正題

防抖

先不說概念,按自己的理解,在單反里,有防抖機制。因為人在拿著單反的時候會手抖(單反重),按下快門的瞬間,照片會糊,所以有防抖機制,以防止新手把照片拍糊。

單反中的防抖是防止抖動,讓人拍出清晰的照片,JavaScript 中的防抖是為了什么?

同理,它的作用也是防止抖動。試想當你頻繁觸發(fā)一個事件時,就會引起不必要的性能損失,那么讓該事件在停止觸發(fā)后再觸發(fā),以此減少部分性能。

防抖的定義

防抖就是要延遲執(zhí)行,你一直操作觸發(fā)事件一直不執(zhí)行,當你停止操作等待多少秒后才執(zhí)行。

也就是說不管事件觸發(fā)頻率有多高,一定在事件觸發(fā) n 秒后執(zhí)行。如果在事件觸發(fā)的 n 秒又觸發(fā)了這個事件,那就以新事件的事件為準,n 秒后才執(zhí)行。總之,要等你觸發(fā)完事件 n 秒內(nèi)不再觸發(fā)事件,它才執(zhí)行。

手寫防抖

根據(jù)定義,我們知道要在時間 n 秒后執(zhí)行,那么我們就用定時器來實現(xiàn):

function debounce(event, wait) {
let timer = null;
return function (...args) {
clearTimeout(timer); // 清除setTimeout,使其回調(diào)函數(shù)不執(zhí)行
timer = setTimeout(() => {
event.apply(this, args)
}, wait)
}
}

代碼很簡單,即當還在觸發(fā)事件時,就清除 timer,使其在 n 秒后執(zhí)行,但此寫法首次不會立即執(zhí)行,為其健壯性,需加上判斷是否第一次執(zhí)行的第三個參數(shù) flag,判斷其是否立即執(zhí)行。

function debounce(event, wait, flag) {
let timer = null;
return function (...args) {
clearTimeout(timer)
if (!timer && flag) {
event.apply(this, args)
} else {
timer = setTimeout(() => {
event.apply(this, args)
}, wait)
}
}
}

防抖場景

窗口大小變化,調(diào)整樣式

window.addEventListener('resize', debounce(handleResize, 200))

搜索框,輸入后1000毫秒搜索

debounce(fetchSelectData, 300)

表單驗證,輸入 1000 毫秒后驗證

debounce(validator, 1000)

防抖帝王庫

兩大工具庫都有防抖源碼,可供參考:

  • lodash-debounce。
  • underscore-debounce。

節(jié)流

顧名思義,一節(jié)一節(jié)的流,就好似控制水閥,在事件不斷觸發(fā)的過程中,固定時間內(nèi)執(zhí)行一次事件。

手寫節(jié)流

因為是固定時間內(nèi)執(zhí)行一次時間,所以我們有兩種實現(xiàn)方法,一用時間戳,二用定時器。

時間戳

function throttle(event, wait) {
let pre = 0;
return function (...args){
if (new Date() - pre > wait) {
// 當 n 秒內(nèi)不重復(fù)執(zhí)行
pre = new Date();
event.apply(this, args)
}
}
}

使用時間戳雖然能實現(xiàn)節(jié)流,但是最后一次事件不會執(zhí)行。

定時器

function throttle(event, wait) {
let timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
timer = null;
event.apply(this, args)
}, wait)
}
}
}

使用定時器實現(xiàn)節(jié)流,雖然最后一次能觸發(fā),但是第一次不會觸發(fā)。

時間戳 + 定時器。

為解決第一次和最后一次都可以觸發(fā),把兩者結(jié)合起來。

function throttle(event, wait) {
let pre = 0, timer = null;
return function (...args) {
if (new Date() - pre > wait) {
clearTimeout(timer);
timer = null;
pre = new Date();
event.apply(this, args)
} else {
timer = setTimeout(() => {
event.apply(this, args)
}, wait)
}
}
}

節(jié)流場景

scroll 滾動

window.addEventListener('scroll', throttle(handleScroll, 200))

input 動態(tài)搜索

throttle(fetchInput, 300)

節(jié)流帝王庫

  • lodash-throttle。
  • underscore-throttle。

總結(jié)

防抖:只執(zhí)行最后一次。事件持續(xù)觸發(fā),但只有等事件停止觸發(fā)后 n 秒后才執(zhí)行函數(shù)。

節(jié)流:控制執(zhí)行頻率。持續(xù)觸發(fā),每 n 秒執(zhí)行一次函數(shù)。

對比圖:

責任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2021-05-08 07:53:33

面試線程池系統(tǒng)

2020-11-24 07:48:32

React

2021-08-10 18:36:02

Express原理面試

2020-10-20 09:12:57

axios核心原理

2022-08-27 13:49:36

ES7promiseresolve

2020-10-23 09:26:57

React-Redux

2023-11-28 17:49:51

watch?computed?性能

2020-10-15 12:52:46

SpringbootJava編程語言

2022-10-31 11:10:49

Javavolatile變量

2021-04-22 07:49:51

Vue3Vue2.xVue3.x

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫

2023-12-18 07:37:17

JavaScript防抖節(jié)流

2020-04-30 10:24:35

Spring循環(huán)依賴Java

2021-05-20 08:54:16

Go面向對象

2020-04-16 08:22:11

HTTPS加解密協(xié)議

2010-08-23 15:06:52

發(fā)問

2019-06-17 05:03:37

memcache內(nèi)核架構(gòu)

2022-05-24 08:03:28

InnoDBMySQL數(shù)據(jù)

2021-08-03 06:57:36

Js事件節(jié)流

2021-06-03 08:55:54

分布式事務(wù)ACID
點贊
收藏

51CTO技術(shù)棧公眾號