最近出去面試了一下,收穫頗多!!!
之前的我,追求實際,比較追求實用價值,然而最近面試,傳說中的面試造火箭,工做擰螺絲,居然被我遇到了。雖然不少知識點在實際工做中並不常常用到,但人家就是靠這個來篩選人才的!!!前端
在大學裏,你可能會感受到微積分沒啥用處,去菜市場買菜,你不可能用到微積分吧,可是呢,這個知識卻決定了你能在哪一個菜市場買菜。請細品!面試
關於前端方面,我用的是jQuery,前端採用Ajax請求數據,後端返回JSON數據,獲得數據後,再經過jQuery去操做DOM。後端
這裏可能有個誤解,不少人會覺得jQuery是一種框架,然而現實並不是如此,它只是個工具庫而已,簡化了JavaScript的一些語法。可能不少人用習慣了jQuery後,甚至都分不清jQuery語法跟JavaScript語法。jQuery能作的事情,JavaScript也能作,只是簡單地簡化了一些寫法。緩存
閒話少說,開始正文。安全
從概念上來說,所謂的閉包指的是一個函數,一個什麼樣的函數呢?有權訪問另外一個函數做用域中的變量的函數。
直觀點來說,JavaScript的閉包就是函數中嵌套函數。
本質上來說,是由於做用域而產生一種特殊的狀況,從而致使函數內部的變量沒法進行銷燬。若是再去深究的話,會出現個做用域鏈,這裏面比較難理解。也是閉包產生的根本緣由。
舉個例子:服務器
function myMethod(){ var num=6; return function(){ var n=0; console.log(++n); console.log(++num); } } myMethod();//執行後,返回的是個方法(就是所謂的閉包),由於這個方法中還用到了myMethod裏面的變量num,會致使num沒法釋放。 //能夠證實 var myFn=myMethod();//將返回的方法用變量保存起來 myFn();//此時的n=1,num=7 num沒有被銷燬,仍然保存着值。這即是閉包的精髓所在,有點像C#/JAVA裏面的靜態變量 myFn();//此時的n=1,num=8 myMethod()();//若是這樣運行的話,輸出永遠是n=1,num=7 跟上面是有區別的,上面是用了個變量將其保存了起來。
閉包的優缺點以下:
優勢:一、保護函數內部的變量安全,實現封裝
二、能夠把這個變量看成緩存來使用
弊端:沒法銷燬變量,使用不當,容易形成內存泄漏閉包
你可能會問,閉包的使用場景究竟是什麼呢?
這個問題可能令你非常疑惑,我也想了好久。直到最近的一次面試,才豁然開朗。接下來看看js的防抖跟節流。框架
防抖,從字面上來理解,即是防止抖動。
這個,咱們應該會常常接觸到,可能本身不知道而已。咱們常用百度吧,沒事百度搜索一下。在這裏,當咱們輸入關鍵詞的時候,會出現一些聯想詞,供咱們去選擇。這裏面便用到了防抖。
試想,若是是咱們,怎麼去實現這個功能,正常狀況下,咱們確定會這樣寫函數
<input type="text" id="txt_test" /> //相應的js代碼 var txt_test=document.getElementById("txt_test"); txt_test.oninput=function(){ console.log(txt_test.value); //其餘代碼 請求後端數據 }
對應的結果
這樣寫,的確不錯。每輸入一個字符,觸發一次輸入事件。工具
聯想到實際
現實中使用百度的人成千上萬,那每次輸入一個字符,請求後端一次,這麼多人的話同時使用百度的話,那請求也太多了,確定會致使服務器壓力賊大,咱們知道,這些請求中不少是沒有什麼實際意義的,基於這種場景,怎麼優化呢?
試想一下,現實中,咱們是怎麼搜索的?
當咱們搜索ghost的時候,應該是快速地輸入,不可能一個字符一個字符的輸入的吧,那打字速度也忒慢了吧。當輸入完的時候,確定會停頓一下,而這時候再去觸發一次輸入事件豈不正好?此時,防抖,應運而生。
function debounce(fn,wait) { var timeout = null; // 建立一個標記用來存放定時器的返回值 return function () { clearTimeout(timeout); //清除定時器 //建立新的 setTimeout timeout = setTimeout(function(){ fn(); }, wait); }; } // 處理函數 function handle() { console.log(document.getElementById("kw").value); } //輸入框事件 document.getElementById("kw").addEventListener('input', debounce(handle,5000));
以上的代碼即是百度搜索中,無論怎麼輸入,只有在輸入完成後,停頓5s(這個時間故意設置這麼長的),纔會觸發一次handle方法。
咱們應該也會常常接觸到,好比打開一個網頁,往下滾動的時候,會出現滾動條,當滾動到必定的程度時,會出現一個返回頂部的按鈕,點擊一下,便會返回到頂部。在這裏,便會用到節流。
試想,若是是咱們,須要實現以上的功能,咱們是如何寫代碼的。
首先,先寫一個div經過position:fixed;display:none;固定到頁面右下角。而後寫一個滾動事件,
window.onscroll=function(e){ //相應的處理代碼 handler();距離多少的位置,顯示按鈕或者隱藏按鈕。 } function handler(){ console.log("滾動事件觸發"); }
在這裏,當咱們向下滾動頁面的時候,你會發現,這個onscroll事件觸發的頻率過高過高,稍微向下滾動一丟丟,就已經觸發了不少次,並且其中不少的觸發並無實在的意義,如何減小觸發的頻率,減小那麼多的計算操做呢?
現實中,屏幕刷新率通常在60HZ,咱們看到的靜態畫面並非徹底不動的,只是動的太快,人眼沒法覺察出,誤覺得是不動的。若是過慢的話,咱們天然會看得出來,過快的話,沒啥實際意義,刷新的過快了,經過人眼,咱們仍是認爲屏幕是不動的。
既然這樣,那可不能夠這樣?
在人眼識別的範圍內,間接地去觸發這個事件。豈不正好?這時候,節流便誕生了。
所謂的節流呢,其思想指的就是某些代碼不能夠在沒有間斷的狀況下連續重複執行。相似的還有onresize等事件。
function throttle(fn,delay){ var canRun=true;//經過閉包保存該變量 return function(){ if(!canRun) return;//馬上返回 canRun=false; setTimeout(function(){ fn(); canRun=true; },delay); }; } function handle(){ console.log(123); } window.addEventListener("scroll",throttle(handle,2000));
以上的代碼即是觸發窗口滾動事件後,每2s執行一次handle方法。
以上的防抖跟節流的方法,都是比較基礎的方法。至於怎麼升級,就靠我的了。
防抖跟節流都用到了閉包,
使用的都是計時器setTimeout,
防抖是某個事件觸發後幾秒後執行相應的方法,
而節流是某個事件觸發後周期性執行相應的方法。