福利在此前端
www.bilibili.com/video/bv1Tr…git
二話不說 輪子我都會造 還怕你面試問嗎? 一天造一個輪子,幹就完了。github
(計劃趕不上變化 隨時迭代 歡迎留言 隨時摸魚)面試
防抖和節流能夠說是一對好基友,也是前端面試的手寫熱點考題。防抖和節流其實都是在規避頻繁觸發回調致使大量計算,從而影響頁面發生抖動甚至卡頓。簡單的說將屢次回調好比頁面點擊或ajax調用變爲一次。防抖和節流的區別在於以第一次爲準仍是最後一次爲準。ajax
在一段時間內,不論觸發多少次調用,都以第一次爲準。 輸入框補全提示,只須要每兩秒補全一次。算法
用測試用例表示設計模式
it("節流Throttle", (done) => {
const { throttle } = require("../index"); // 定義一個Mock函數 const mockFn = jest.fn(); // 封裝爲節流方法 const fn = throttle(mockFn, 10); // 同步調用兩次 fn(1); fn(2); setTimeout(() => { const calls = mockFn.mock.calls; // 斷言 mock方法只調用一次 expect(calls.length).toBe(1); // 根據參數判斷以第一次調用爲準 expect(calls[0][0]).toBe(1); done(); }, 50); }); 複製代碼
在一段時間內,不論觸發多少期回調,都已最後一次爲準。 好比:以用戶拖拽改變窗口大小,觸發 resize 事件爲例,會觸發組件從新佈局,這裏面只有最後一次調用是有意義的。markdown
it("防抖Debounce", (done) => {
const { debounce } = require("../index"); const mockFn = jest.fn(); // 封裝一個防抖函數 const fn = debounce(mockFn, 10); // 連續兩次調用 fn(1); fn(2); setTimeout(() => { const calls = mockFn.mock.calls; // 斷言只調用一次 expect(calls.length).toBe(1); // 斷言以最後一次調用爲準 expect(calls[0][0]).toBe(2); done(); }, 50); }); 複製代碼
主要思路利用時間戳判斷,每次調用判斷和上一次調用的時間差別肯定是否須要調用。 throttle實際是一個工廠函數,能夠將一個函數封裝爲一個帶有節流功能的函數。app
module.exports.throttle = (fn, delay) => {
// 定義上次觸發時間 let last = 0; return (...args) => { const now = + Date.now(); console.log("call", now, last, delay); if (now > last + delay) { last = now; fn.apply(this, args); } }; }; 複製代碼
實現的話能夠使用定時器執行函數,新調用發生時若是舊調用沒有執行就清除以前的定時器。框架
/**
* 防抖Debounce */ module.exports.debounce = (fn, delay) => { let timer; return (...args) => { // 判判定時器是否存在,清除定時器 if (timer) { clearTimeout(timer); } // 從新調用setTimeout timer = setTimeout(() => { fn.apply(this, args); }, delay); }; }; 複製代碼
OK 任務完成
本文使用 mdnice 排版