瀏覽器中某些計算和處理很是昂貴。好比當鼠標響應resize
, touchmove
,scroll
等操做時,綁定的函數觸發的頻率會很高,若是該函數稍微複雜一些,響應速度會遠遠跟不上觸發頻率,便會出現卡頓,延遲,假死等現象。javascript
下面來看一個例子,根據輸入框輸入的數據發送ajax請求:html
<!DOCTYPE html>
<html>
<head>
<title>普通處理</title>
</head>
<body>
<div>
普通處理:<input type="text" id="index"/>
</div>
<script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } document.querySelector('#index').addEventListener('keyup', e => { ajax(e.target.value) }) } </script>
</body>
</html>
複製代碼
普通處理結果以下:java
如上圖所見,在輸入時會不斷的發送請求,很是浪費資源。爲優化性能,咱們能夠使用防抖或節流來防止函數被高頻調用。ajax
在事件被觸發n秒後,再去執行回調函數。若是n秒內該事件被從新觸發,則從新計時。結果就是將頻繁觸發的事件合併爲一次,且在最後執行。瀏覽器
電梯5秒後會關門開始運做,若是有人進來,等待5秒,5秒以內又有人進來,5秒等待從新計時...直至超過5秒,電梯纔開始運做。服務器
input輸入數據時請求服務器等。函數
每當事件觸發,就去重置定時器。直至最後一次事件被觸發,n秒後再去執行回調函數。性能
<!DOCTYPE html>
<html>
<head>
<title>加入防抖</title>
</head>
<body>
<div>
加入防抖:<input type="text" id="debounce"/>
</div>
<script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function debounce (fn, delay) { return args => { clearTimeout(fn.id) fn.id = setTimeout(() => { fn.call(this, args) }, delay) } } const debounceAjax = debounce(ajax, 1000) document.querySelector('#debounce').addEventListener('keyup', e => { debounceAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼
加入防抖結果以下:優化
規定一個時間n,n秒內,將觸發的事件合併爲一次並執行。ui
電梯等第一我的進來以後,5秒後準時運做,不等待,若5秒內還有人進來,也不重置。
resize
,touchmove
移動DOM,上拉列表加載數據等。
<!DOCTYPE html>
<html>
<head>
<title>加入節流-定時器</title>
</head>
<body>
<div>
加入節流-定時器:<input type="text" id="throttle"/>
</div>
<script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle (fn, delay) { return args => { if (fn.id) return fn.id = setTimeout(() => { fn.call(this, args) clearTimeout(fn.id) fn.id = null }, delay) } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼
加入節流-定時器結果以下:
<!DOCTYPE html>
<html>
<head>
<title>加入節流-時間戳</title>
</head>
<body>
<div>
加入節流-時間戳:<input type="text" id="throttle"/>
</div>
<script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle (fn, delay) { let last = 0 return args => { let now = Date.now() if (now > last + delay) { fn.call(fn, args) last = now } } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼
加入節流-時間戳結果以下:
<!DOCTYPE html>
<html>
<head>
<title>加入節流-定時器 & 時間戳</title>
</head>
<body>
<div>
加入節流-定時器 & 時間戳:<input type="text" id="throttle"/>
</div>
<script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle(fn, delay) { let last return args => { let now = Date.now() if (last && now < last + delay) { clearTimeout(fn.id) fn.id = setTimeout(() => { fn.call(this, args) last = now }, delay) } else { fn.call(this, args) last = now } } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼
加入節流-定時器 & 時間戳結果以下:
本文主要介紹了防抖與節流的實現方式。其中,防抖
的核心思想是高頻操做執行結束,n秒後僅執行一次;而節流
是每隔一段時間就會執行一次。
感謝閱讀,若有問題,歡迎指正。