堅持造輪子次日 - 防抖與節流

福利在此前端

www.bilibili.com/video/bv1Tr…git

二話不說 輪子我都會造 還怕你面試問嗎? 一天造一個輪子,幹就完了。github

看點

  • 針對大廠筆試、面試必考手寫題目
  • TDD方式開發
  • 配合視頻講解

造輪子計劃

(計劃趕不上變化 隨時迭代 歡迎留言 隨時摸魚)面試

  • 框架基礎
    • 框架基礎
    • JS基礎
      • Promise.all/race
      • 路由
      • new
      • call/apply/bind
      • Object.create
      • 深拷貝、淺拷貝
    • 算法、設計模式
      • 二分查找
      • 快排
      • 二分查找
      • 冒泡排序
      • 選擇排序
      • 訂閱發佈
      • 斐波那契算法
      • 去重

    防抖和節流

    防抖和節流能夠說是一對好基友,也是前端面試的手寫熱點考題。防抖和節流其實都是在規避頻繁觸發回調致使大量計算,從而影響頁面發生抖動甚至卡頓。簡單的說將屢次回調好比頁面點擊或ajax調用變爲一次。防抖和節流的區別在於以第一次爲準仍是最後一次爲準。ajax

    需求

    1. 節流Throttle - 調用屢次、只第一次調用有效

    在一段時間內,不論觸發多少次調用,都以第一次爲準。 輸入框補全提示,只須要每兩秒補全一次。算法

    用測試用例表示設計模式

    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); }); 複製代碼

    2. 防抖Debounce 最後一次爲準

    在一段時間內,不論觸發多少期回調,都已最後一次爲準。 好比:以用戶拖拽改變窗口大小,觸發 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 任務完成

    關注全棧然叔 帶你堅持每天造輪子 (週末休息 拒絕996)

    本文使用 mdnice 排版

相關文章
相關標籤/搜索