這裡以判斷頁面是否滾動到底部為例,普通的做法就是監聽window
物件的scroll
事件,然後再函式體中寫入判斷是否滾動到底部的邏輯:
這樣做的乙個缺點就是比較消耗效能,因為當在滾動的時候,瀏覽器會無時不刻地在計算判斷是否滾動到底部的邏輯,而在實際的場景中是不需要這麼做的,在實際場景中可能是這樣的:在滾動過程中,每隔一段時間在去計算這個判斷邏輯。而函式節流所做的工作就是每隔一段時間去執行一次原本需要無時不刻地在執行的函式,所以在滾動事件中引入函式的節流是乙個非常好的實踐:
加上函式節流之後,當頁面再滾動的時候,每隔300ms
才會去執行一次判斷邏輯。
簡單來說,函式的節流就是通過閉包儲存乙個標記(canrun = true
),在函式的開頭判斷這個標記是否為true
,如果為true
的話就繼續執行函式,否則則 return 掉,判斷完標記後立即把這個標記設為false
,然後把外部傳入的函式的執行包在乙個settimeout
中,最後在settimeout
執行完畢後再把標記設定為true
(這裡很關鍵),表示可以執行下一次的迴圈了。當settimeout
還未執行的時候,canrun
這個標記始終為false
,在開頭的判斷中被 return 掉。
很明顯,這樣的做法不好的是當使用者輸入第乙個字元的時候,就開始請求判斷了,不僅對伺服器的壓力增大了,對使用者體驗也未必比原來的好。而理想的做法應該是這樣的,當使用者輸入第乙個字元後的一段時間內如果還有字元輸入的話,那就暫時不去請求判斷使用者名稱是否被占用。在這裡引入函式防抖就能很好地解決這個問題:
其實函式防抖的原理也非常地簡單,通過閉包儲存乙個標記來儲存settimeout
返回的值,每當使用者輸入的時候把前乙個settimeout
clear 掉,然後又建立乙個新的settimeout
,這樣就能保證輸入字元後的interval
間隔內如果還有字元輸入的話,就不會執行fn
函式了。
function debounce(fn, interval = 300) , interval);};}
其實函式節流與函式防抖的原理非常簡單,巧妙地使用settimeout
來存放待執行的函式,這樣可以很方便的利用cleartimeout
在合適的時機來清除待執行的函式。
使用函式節流與函式防抖的目的,在開頭的栗子中應該也能看得出來,就是為了節約計算機資源。
函式防抖與函式節流
函式防抖 debounce 當呼叫動作過n毫秒後,才會執行該動作,若在這n毫秒內又呼叫此動作則將重新計算執行時間 函式節流 throttle 預先設定乙個執行週期,當呼叫動作的時刻大於等於執行週期則執行該動作,然後進入下乙個新週期 函式節流 throttle 與函式防抖 debounce 都是為了限...
函式防抖與函式節流
前言 有一些瀏覽器事件我們不希望它很頻繁的觸發,如調整視窗大小 onresize 監聽滾動條滾動 onscroll 如果這些監聽事件需要呼叫介面的話一秒內可能會呼叫上百次,這樣坑定是有問題的。函式防抖 debounce 如果有人進電梯 觸發事件 那電梯將在10秒鐘後出發 執行事件 這時如果又有人進電...
函式防抖與函式節流
有一些瀏覽器事件可以在很短的事件內快速觸發多次,例如調整視窗大小或向下滾動頁面。例如,如果將事件 繫結到視窗滾動事件上,並且使用者繼續非常快速地向下滾動頁面,你的事件可能會在3秒的範圍內被觸發數千次。這可能會導致一些嚴重的效能問題,如果在面試中討論構建應用程式和事件,如滾動 視窗調整大小,或鍵盤按下...