平時我們在開發中,會經常使用到resize和movesemove事件,這些事件會在短時間內頻繁的執行事件繫結程式,我們知道頻繁的操作DOM會帶來很大的效能消耗,頁面會促發迴流和重繪。有時候頁面會出現卡頓,在IE瀏覽器下可能直接崩潰。這時候節流函式就發揮作用了。
什麼是函式節流?
簡單講就是讓一個函式無法在短時間內連續呼叫,只有當上一次函式執行後過了規定的時間間隔,才能進行下一次該函式的呼叫。或者說你在操作的時候不會馬上執行該函式,而是等你不操作的時候才會執行。
函式截流的原理
通過使用定時器,在操作的時候讓函式延時執行,如果在這個時間內還在操作,則清除原來的定時器,再建立一個新的定時器執行
方式一:
最簡單的操作方式,在操作的的時候清除上次的定時器,不操作的事後在執行callBack回撥
//封裝
/**
* @ { Function} callBack 回撥程式
*/
function throttleFn(callBack){
clearTimeout(method.timer);
method.timer=setTimeout(()=>{
method()
},100)
}
//呼叫
window.onresize=function(){
throttleFn(callBack)
}
複製程式碼
方式二
優勢在於把延遲時間當做變數,而且使用閉包保護私有變數,缺點就是雖然使用apply把呼叫throttleFn時的this上下文傳給執行函式,但畢竟不夠靈活
//封裝
/**
* @ { Function} callBack 回撥程式
* @ { Number } delay 延時時間
* return { Function }
*/
function thorttleFn(callBack,delay){
var timer=null;
return function(){
var context=this;
clearTimeout(timer);
timer=setTimeout(()=>{
callBack.apply(context,arguments)
},delay)
}
}
//呼叫
window.onresize=thorttleFn(myFunc,300)
複製程式碼
方式三(個人認為效能最優)
擴充深化函式節流
其實函式節流的出發點,就是讓一個函式不要執行得太頻繁,減少一些過快的呼叫來節流,減少效能消耗。當你在操作resize和mousemove事件的時候,瀏覽器其實是有設定一個時間間隔,這個時間是多少我們不清楚,而且他們沒有提供引數去設定,所以需要我們在他們的基礎上再去做一些改變。真正的節流應該是在可接受的範圍內儘量延長這個呼叫時間,也就是我們自己控制這個執行頻率,讓函式減少呼叫以達到減少計算、提升效能的目的。假如原來是16ms執行一次,我們如果發現resize時每50ms一次也可以接受,那肯定用50ms做時間間隔好一點。
/**
* @ { Function} callBack 回撥程式
* @ { Number } delay 延時時間
* @ { Number } intervalTime 間隔時間
* return { Function }
*/
function thorttleFn(callBack,delay,intervalTime){
var timer=null; // 定時器變數
var time=0; // 時間變數
return function(){
var context=this;
var curTime=new Date(); // 當前執行的時間
clearTimeout(timer); // 清除上次的定時器
if(!time){
time=curTime;
}
// 當前執行時間距離上次執行的時間是否大於等於間隔時間
if(curTime - time >= intervalTime){
time=curTime;
callBack.apply(context,arguments)
}else{
timer=setTimeout(()=>{
callBack.apply(context,arguments)
},delay)
}
}
}
//呼叫
window.onresize=thorttleFn(myFunc,50,300)
複製程式碼