這一篇文章我想寫一下防抖與節流,由於我本身不是很理解並且說實話,之前知道,可是老忘,雖然概念還有一些簡單的寫法會,但仍是缺少練習和深入的理解。app
當咱們不加防抖或節流的時候就像這樣,鼠標滑過觸發這麼屢次,因此咱們一個使用防抖或節流來限制它的請求次數而不是觸發次數。關於防抖與節流的應用和解釋自行查找資料。函數
<div id="app"></div> function fn(e) { console.log(this); console.log(e); app.innerHTML = num ++; }
1.防抖this
function debounce(fn, delay) { let timer = null; return function(){ clearTimeout(timer); timer = setTimeout(function () { fn(); }, delay); } }
使用節流後spa
app.onmousemove = fdebounce(fn, 1000);
咱們發現次數減小了太多,由於只要你在delay時間內不停地觸發就不會執行直到你的間隔時間大於delay纔會執行。3d
咱們來看一下this和event。
this是window,event是undefined。code
function debounce(fn, delay) { let timer = null, that; return function(e){ that = this; clearTimeout(timer); timer = setTimeout(function () { //this指向window(非嚴格模式) fn.apply(that, [e]); }, delay); } }
或者是blog
function debounce(fn, delay) { let timer = null; return function(e){ clearTimeout(timer); timer = setTimeout(()=>{ //箭頭函數 fn.apply(this, [e]); }, delay); } }
function debounce(fn, delay, immediate) { let timer = null, that; return function (e) { that = this; clearTimeout(timer); if(immediate){ //是否當即執行 if(!timer){ // 若是沒有設置定時器就先執行 fn.apply(that, [e]); } timer = setTimeout(function () { timer = null;// 設置定時器,使其在delay毫秒內不能執行,過了delay毫秒後在執行 }, delay); }else{ //不然延時執行 timer = setTimeout(function () { fn.apply(that, [e]) }, delay); } }; } //這個if...else只能執行一個,要不先執行,要不延時執行
一開始會執行一次,由於錄製不能顯示鼠標因此理解一下。事件
function throttle(fn, delay) { let last = 0, //上次執行時間 now; //執行時的時間 return function (e) { now = Date.now(); //當前時間 if(now - last >= delay){ //若是兩次時間間隔大於delay,就執行 last = now; //從新賦值 fn(); } }; }
在規定時間delay毫秒內總會執行一次事件。rem
function throttle(fn, delay) { let that, timer = null; return function (e) { that = this; if(!timer){ //若是沒設置定時器就執行 timer = setTimeout(function () { fn.apply(that, [e]); timer = null; //果delay毫秒就設置timer,這樣就能delay執行一次 }, delay); } }; }
function throttle(fn, delay) { let last = 0, //上次執行時間 now; //執行時的時間 return function (e) { now = Date.now(); //當前時間 if(now - last >= delay){ //若是兩次時間間隔大於delay,就執行 last = now; //從新賦值 fn.apply(this, [e]); } }; }
區別it
因此能夠結合一下他們兩個。
function throttle(fn, delay) { let last = 0, //上次執行時間 now, //當前時間 leftTime, //剩餘時間 that, timer = null; return function (e) { that = this; now = Date.now(); leftTime = delay - (now - last); if(leftTime <= 0){ //保證一開始就執行(先執行) last = now; fn.apply(that, [e]); }else{ timer = setTimeout(function() { //延時執行 fn.apply(that, [e]); timer = null; },delay) } }; }
這樣作整體思路沒錯,可是第一次會執行之後就是兩個一塊兒執行,由於條件都知足。
function throttle(fn, delay) { let last = 0, now, leftTime, that, timer = null; return function (e) { that = this; now = Date.now(); leftTime = delay - (now - last); if(leftTime <= 0){ if(timer){ //若是有定時器就清除 clearTimeout(timer); timer = null; } last = now; fn.apply(that, [e]); }else if(!timer){ timer = setTimeout(function() { last = now; //若是時間知足就讓他不知足 //總之除了第一次就只讓其中一個執行 fn.apply(that, [e]); timer = null; },delay) } }; }
一開始執行一次(時間戳),最後中止在執行一次(setTimeOut)。