聽說阿里有一道面試題就是談談函數節流和函數防抖。
糟了,這可觸碰到個人知識盲區了,好像聽也沒聽過這2個東西,痛定思痛,趕忙學習學習。here we go!javascript
在事件被觸發n秒後再執行回調,若是在這n秒內又被觸發,則從新計時。
看一個🌰(栗子):html
//模擬一段ajax請求 function ajax(content) { console.log('ajax request ' + content) } let inputa = document.getElementById('unDebounce') inputa.addEventListener('keyup', function (e) { ajax(e.target.value) })
看一下運行結果:前端
能夠看到,咱們只要按下鍵盤,就會觸發此次ajax請求。不只從資源上來講是很浪費的行爲,並且實際應用中,用戶也是輸出完整的字符後,纔會請求。下面咱們優化一下:java
//模擬一段ajax請求 function ajax(content) { console.log('ajax request ' + content) } function debounce(fun, delay) { return function (args) { let that = this let _args = args clearTimeout(fun.id) fun.id = setTimeout(function () { fun.call(that, _args) }, delay) } } let inputb = document.getElementById('debounce') let debounceAjax = debounce(ajax, 500) inputb.addEventListener('keyup', function (e) { debounceAjax(e.target.value) })
看一下運行結果:git
能夠看到,咱們加入了防抖之後,當你在頻繁的輸入時,並不會發送請求,只有當你在指定間隔內沒有輸入時,纔會執行函數。若是中止輸入可是在指定間隔內又輸入,會從新觸發計時。
再看一個🌰:github
let biu = function () { console.log('biu biu biu',new Date().Format('HH:mm:ss')) } let boom = function () { console.log('boom boom boom',new Date().Format('HH:mm:ss')) } setInterval(debounce(biu,500),1000) setInterval(debounce(boom,2000),1000)
看一下運行結果:面試
這個🌰就很好的解釋了,若是在時間間隔內執行函數,會從新觸發計時。biu會在第一次1.5s執行後,每隔1s執行一次,而boom一次也不會執行。由於它的時間間隔是2s,而執行時間是1s,因此每次都會從新觸發計時ajax
我的理解 函數防抖就是法師發技能的時候要讀條,技能讀條沒完再按技能就會從新讀條。
規定在一個單位時間內,只能觸發一次函數。若是這個單位時間內觸發屢次函數,只有一次生效。
看一個🌰:瀏覽器
function throttle(fun, delay) { let last, deferTimer return function (args) { let that = this let _args = arguments let now = +new Date() if (last && now < last + delay) { clearTimeout(deferTimer) deferTimer = setTimeout(function () { last = now fun.apply(that, _args) }, delay) }else { last = now fun.apply(that,_args) } } } let throttleAjax = throttle(ajax, 1000) let inputc = document.getElementById('throttle') inputc.addEventListener('keyup', function(e) { throttleAjax(e.target.value) })
看一下運行結果:app
能夠看到,咱們在不斷輸入時,ajax會按照咱們設定的時間,每1s執行一次。
結合剛剛biubiubiu的🌰:
let biubiu = function () { console.log('biu biu biu', new Date().Format('HH:mm:ss')) } setInterval(throttle(biubiu,1000),10)
無論咱們設定的執行時間間隔多小,老是1s內只執行一次。
我的理解 函數節流就是fps遊戲的射速,就算一直按着鼠標射擊,也只會在規定射速內射出子彈。
debounce
throttle
參考連接: http://www.cnblogs.com/zichi/...
這是高程中的經典代碼:
function throttle(method, context) { clearTimeout(method.tId); method.tId = setTimeout(function () { method.call(context); }, 100) }
咱們經過上面的例子知道,其實這段函數應該是debounce函數防抖,而不是函數節流,不少文章也都會拿這段代碼來作例子,函數自己沒錯,可是命名錯了。
原做者的這段話就寫的很好,
就以 throttle 爲例,某日,老師給你佈置了一個做業,讓你深刻理解一下 throttle,次日上課來聊聊。張三內心很是高興,這個概念在經典書籍《JavaScript高級程序設計》中見過,打開一看,就兩頁,並且解釋地很是清晰,看完就高興地幹別的事情去了。而李四,以爲高程三講的有點少,而去谷歌了下其餘關於 throttle 的知識點,興奮地看到 throttle 函數的好幾種寫法,發現高程三隻是用了最簡單的方式,還有更優雅運用場景更多的寫法,或許此時他已經發現和 throttle 同時出現的還有個 debounce,這是什麼鬼?反正老師沒說,之後再看吧,因而心滿意足地玩遊戲去了。而王五,和李四同樣發現了 debounce,這是什麼?一塊兒瞭解了吧,繼而發現 debounce 的用法竟然和高程三中的 throttle 同樣!繼續挖下去,發現高程三中的 throttle 函數其實應該叫 debounce,看到最後,王五已經把 throttle 和 debounce 完全理解了。
咱們要作王五,而且爭取早日產出一手知識!加油!
本文發佈於薄荷前端週刊,歡迎Watch & Star ★,轉載請註明出處。