當持續觸發事件時,保證必定時間段內只調用一次事件處理函數。也就是一個函數執行一次後,只有大於設定的執行週期後纔會執行第二次。
記憶法:聯繫到水流的流量,我想讓你1s只流出多少水你就只能流多少水,多的水流只能等到下個週期才能流出。
應用場景:如用戶不斷滑動滾輪,規定1s只能真正下滑一次,你滑再多也沒用,只能等到下個週期你再滑纔有用。
實現原理:
A:用函數的閉包來鎖住上一執行的時間,在用這一次執行的時間相比,大於設定的間隔時間則執行
B:也能夠直接把lasTime放到全局去,不用閉包但這樣就很差在事件監聽的時候傳遞參數delay只能寫死javascript
這裏我節流用閉包寫,防抖就不用閉包了java
用閉包就有一個問題,this的指向會很是複雜:
1.throttle函數的執行環境具備全局性,內部this一般是指向window的,而後返回一個匿名函數。
2.返回的匿名函數綁定了事件,this指向監聽的元素(document)
3.fn其實與上面返回匿名函數造成了閉包,且fn也實際上是一個匿名函數,匿名函數的執行具備全局性,fn內部this應該指向window
4這裏用apply修正this指向,使fn內部的this從新指向document閉包
<script type="text/javascript"> function throttle(fn, delay) { console.log(this)//window // 記錄上一次函數觸發的時間 var lastTime = 0; return function() { // 記錄當前函數觸發的時間 var nowTime = Date.now(); if(nowTime - lastTime > delay) { /* fn(); console.log(this)//document */ fn.apply(this)// 修正this指向問題 console.log(this)//document // 同步時間 lastTime = nowTime; } } } document.onscroll = throttle(function() { /*console.log(this)//window*/ console.log(this)//document console.log('scroll事件被觸發了' + Date.now()) }, 1000) </script>
當持續觸發事件時,必定時間段內沒有再觸發事件,事件處理函數纔會執行一次,若是設定的時間到來以前,又一次觸發了事件,就從新開始延時,好比頻繁觸發的某一函數,防抖能夠只讓最後一次執行。記憶法:讓函數執行者冷靜下來後(不一直抖動後),才真正執行。
應用場景:用戶屢次點擊提交表單
不用閉包後結構會很簡單app
<script type="text/javascript"> var timer = null;// 記錄上一次的延時器 function debounce() { console.log(timer) clearTimeout(timer) timer = setTimeout(function() { console.log("aaa") }, 1000) } document.getElementById('btn').onclick = debounce </script>