天天看點

徹底搞懂JavaScript的閉包、防抖跟節流

最近出去面試了一下,收獲頗多!!!

以前的我,追求實際,比較追求實用價值,然而最近面試,傳說中的面試造火箭,工作擰螺絲,竟然被我遇到了。雖然很多知識點在實際工作中并不經常用到,但人家就是靠這個來篩選人才的!!!

徹底搞懂JavaScript的閉包、防抖跟節流

在大學裡,你可能會感覺到微積分沒啥用處,去菜市場買菜,你不可能用到微積分吧,但是呢,這個知識卻決定了你能在哪個菜市場買菜。請細品!

關于前端方面,我用的是jQuery,前端采用Ajax請求資料,後端傳回JSON資料,得到資料後,再通過jQuery去操作DOM。

這裡可能有個誤解,很多人會以為jQuery是一種架構,然而現實并非如此,它隻是個工具庫而已,簡化了JavaScript的一些文法。可能很多人用習慣了jQuery後,甚至都分不清jQuery文法跟JavaScript文法。jQuery能做的事情,JavaScript也能做,隻是簡單地簡化了一些寫法。

閑話少說,開始正文。

從概念上來講,所謂的閉包指的是一個函數,一個什麼樣的函數呢?有權通路另一個函數作用域中的變量的函數。

直覺點來講,JavaScript的閉包就是函數中嵌套函數。

本質上來講,是因為作用域而産生一種特殊的情況,進而導緻函數内部的變量無法進行銷毀。如果再去深究的話,會出現個作用域鍊,這裡面比較難了解。也是閉包産生的根本原因。

舉個例子:

閉包的優缺點如下:

優點:1、保護函數内部的變量安全,實作封裝

2、可以把這個變量當作緩存來使用

弊端:無法銷毀變量,使用不當,容易造成記憶體洩漏

你可能會問,閉包的使用場景到底是什麼呢?

這個問題可能令你很是疑惑,我也想了很久。直到最近的一次面試,才豁然開朗。接下來看看js的防抖跟節流。

防抖,從字面上來了解,便是防止抖動。

這個,我們應該會經常接觸到,可能自己不知道而已。我們經常使用百度吧,沒事百度搜尋一下。在這裡,當我們輸入關鍵詞的時候,會出現一些聯想詞,供我們去選擇。這裡面便用到了防抖。

徹底搞懂JavaScript的閉包、防抖跟節流

試想,如果是我們,怎麼去實作這個功能,正常情況下,我們肯定會這樣寫

對應的結果

徹底搞懂JavaScript的閉包、防抖跟節流

這樣寫,的确不錯。每輸入一個字元,觸發一次輸入事件。

聯想到實際

現實中使用百度的人成千上萬,那每次輸入一個字元,請求後端一次,這麼多人的話同時使用百度的話,那請求也太多了,肯定會導緻伺服器壓力賊大,我們知道,這些請求中很多是沒有什麼實際意義的,基于這種場景,怎麼優化呢?

試想一下,現實中,我們是怎麼搜尋的?

當我們搜尋ghost的時候,應該是快速地輸入,不可能一個字元一個字元的輸入的吧,那打字速度也忒慢了吧。當輸入完的時候,肯定會停頓一下,而這時候再去觸發一次輸入事件豈不正好?此時,防抖,應運而生。

以上的代碼便是百度搜尋中,不管怎麼輸入,隻有在輸入完成後,停頓5s(這個時間故意設定這麼長的),才會觸發一次handle方法。

我們應該也會經常接觸到,比如打開一個網頁,往下滾動的時候,會出現滾動條,當滾動到一定的程度時,會出現一個傳回頂部的按鈕,點選一下,便會傳回到頂部。在這裡,便會用到節流。

試想,如果是我們,需要實作以上的功能,我們是如何寫代碼的。

首先,先寫一個div通過position:fixed;display:none;固定到頁面右下角。然後寫一個滾動事件,

在這裡,當我們向下滾動頁面的時候,你會發現,這個onscroll事件觸發的頻率太高太高,稍微向下滾動一丢丢,就已經觸發了很多次,而且其中很多的觸發并沒有實在的意義,如何減少觸發的頻率,減少那麼多的計算操作呢?

現實中,螢幕重新整理率一般在60HZ,我們看到的靜态畫面并不是完全不動的,隻是動的太快,人眼無法覺察出,誤以為是不動的。如果過慢的話,我們自然會看得出來,過快的話,沒啥實際意義,重新整理的過快了,通過人眼,我們還是認為螢幕是不動的。

既然這樣,那可不可以這樣?

在人眼識别的範圍内,間接地去觸發這個事件。豈不正好?這時候,節流便誕生了。

所謂的節流呢,其思想指的就是某些代碼不可以在沒有間斷的情況下連續重複執行。類似的還有onresize等事件。

以上的代碼便是觸發視窗滾動事件後,每2s執行一次handle方法。

以上的防抖跟節流的方法,都是比較基礎的方法。至于怎麼更新,就靠個人了

徹底搞懂JavaScript的閉包、防抖跟節流

防抖跟節流都用到了閉包,

使用的都是計時器setTimeout,

防抖是某個事件觸發後幾秒後執行相應的方法,

而節流是某個事件觸發後周期性執行相應的方法。

徹底搞懂JavaScript的閉包、防抖跟節流