瀏覽器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。這些事件觸發頻率太過頻繁,綁定在這些事件上的回調函數會不停的被調用。會加劇瀏覽器的負擔,致使用戶體驗很是糟糕,不知哪一個大神發明了防抖和節流,用來控制回調函數的次數。javascript
//函數防抖(debounce) function debounce(fn, wait) { var timeout; return function() { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(fn, wait); } } function handle() { console.log(12) } //滾動事件 window.addEventListener("scroll", debounce(handle, 1000))
代碼解釋:先執行debounce(handle, 1000)返回一個匿名函數,而後監聽scroll事件,執行匿名函數,設置一個1秒後執行handle函數的定時器,因爲scroll是不斷觸發的,若是第一次觸發與第二次觸發間隔1秒或者1秒多,第一次觸發scroll會執行handle函數,在控制檯上會打印12,若是間隔小於1秒,由於setTimeout(fn, wait)是要在1秒後執行handle 函數,小於1秒就不執行handle函數,可是timeout定時器已經不爲空,第二次scroll滾動觸發debounce時就執行clearTimeout(timeout),而且執行下面的代碼,由於下面的代碼不是放在else裏面,依次類推。
總結:若是不停的觸發事件,事件間隔大於設定的時間,才執行某個函數。html
若是是input的狀況,這時須要傳遞數據前端
//函數節流(throttle) var throttle = function(func, delay) { console.log("hi") var prev = Date.now(); //返回1970 年 1 月 1日午夜與當前日期和時間之間的毫秒數。 return function() { var now = Date.now(); if (now - prev >= delay) { func() prev = Date.now() } } } function handle() { console.log(Math.random()) } window.addEventListener("scroll", throttle(handle, 1000))
解釋:當持續觸發事件時,每隔必定時間(如200ms)執行一次事件處理函數
先執行throttle(handle, 1000)返回一個匿名函數,而後觸發scroll事件時執行返回的匿名函數,即未滾動的時候已經執行了throttle(handle, 1000)函數java
若是是input的狀況(防抖)jquery
<body> <div style="" class=""> <input type="" id="unDebounce" /> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script type="text/javascript"> function ajax(content) { console.log("ajax request" + content) } function debounce(fun, delay) { var timeout; return function(args) { if (timeout) { clearTimeout(timeout) } timeout = setTimeout(function() { fun(args) }, delay) } } let inputElement = document.getElementById("unDebounce") let debounceAjax = debounce(ajax, 500) inputElement.addEventListener("keyup", function() { //debounceAjax(this.value)放在匿名函數裏面的緣由是當keyup的時候才執行,若是不放在裏面會先執行此函數,致使沒有值 debounceAjax(this.value) }) </script> </body>
上面是用的閉包避免污染全局變量,用全局變量的寫法更簡單些ajax
<script type="text/javascript"> function handle(content){ console.log("input " + content); } var timeout; function debounce(value,handle,wait){ if(timeout){ clearTimeout(timeout) } timeout = setTimeout(function(){ handle(value) },wait) } var inputElement = document.getElementById("unDebounce"); inputElement.addEventListener("input",function(){ debounce(this.value,handle,500) }) </script>
若是是input的狀況(節流) bootstrap
<body> <div style="" class=""> <input type="" id="throttle" /> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script type="text/javascript"> function ajax(content) { console.log("ajax request" + content) } function throttle(func, delay) { var pre = Date.now(); var deferTimer; console.log("pre " + pre) return function(args) { var now = Date.now() console.log("now " + now) console.log(now - pre) if (now - pre >= delay) { func(args) pre = Date.now() } else { clearTimeout(deferTimer); deferTimer = setTimeout(function() { func(args) pre = Date.now() }, delay) } } } var throttleAjax = throttle(ajax, 2000) var inputc = document.getElementById('throttle') inputc.addEventListener('keyup', function() { throttleAjax(this.value) }) </script> </body>
防抖和節流的區別: 防抖是根據事件間隔是否大於設定的值來決定回調函數是否執行(取決於事件間隔,或者最後一次滾動); 節流是根據事件不停觸發時時間間隔大於設定的值才執行回調函數(每隔多少秒執行一次);瀏覽器
公衆號:前端之攻略閉包