jsliang 求職系列 - 21 - 瀏覽器緩存

一 目錄

不折騰的前端,和鹹魚有什麼區別前端

目錄
一 目錄
二 前言
三 正文
四 刷題

二 前言

返回目錄

三 正文

返回目錄
  • 爲何須要瀏覽器緩存?

經過從輸出 URL 到頁面呈現咱們能夠知道,瀏覽器若是每次都要請求加載頁面,會至關費時間。git

而若是咱們將某些網頁存儲到瀏覽器緩存中,這樣當咱們打開一個網頁的時候,就會去查詢瀏覽器緩存,看是否有請求的文件。github

若是有,那就攔截請求,返回緩存文件,並結束請求,而不會去服務器下載。算法

  • 爲何須要瀏覽器緩存淘汰策略?

使用過 360 等殺毒軟件的人都知道,它會時不時提醒你瀏覽器有多少緩存能夠清理了……數組

由於瀏覽器中的緩存是一種本地保存資源副本,它的大小是有限的,當咱們請求次數過多的時候,緩存空間就會被塞滿。瀏覽器

這個時候,就須要判斷哪些緩存數據須要被保留,哪些數據須要被清理。緩存

所以,瀏覽器緩存也有屬於本身的策略:瀏覽器緩存淘汰策略服務器

最多見的淘汰策略有 FIFO(先進先出)、LFU(最少使用)、LRU(最近最少使用)。網絡

  • 什麼是 LRU(最近最少使用)?

LRU(Least recently used),即最近最少使用算法,該算法根據數據的歷史訪問記錄來進行淘汰數據,其核心思想是 「若是數據最近被訪問過,那麼未來被訪問的概率也更高」。數據結構

簡單來講:瀏覽器緩存空間很小,只能緩存 10 個網頁,那麼只會保存最近訪問的 10 個網頁

通用實現原理:

  1. 新數據將被插入到鏈表表頭
  2. 訪問緩存中的數據時,將該數據移動到鏈表表頭
  3. 當鏈表滿時,將鏈表尾部的數據丟棄。

四 刷題

返回目錄

話很少說,咱們刷下題就懂了:

運用你所掌握的數據結構,設計和實現一個  LRU (最近最少使用) 緩存機制。

它應該支持如下操做: 獲取數據 get 和 寫入數據 put 。

獲取數據 get(key):
  若是關鍵字 (key) 存在於緩存中,
  則獲取關鍵字的值(老是正數),不然返回 -1。

寫入數據 put(key, value):
  若是關鍵字已經存在,則變動其數據值;
  若是關鍵字不存在,則插入該組「關鍵字/值」。
  當緩存容量達到上限時,
  它應該在寫入新數據以前刪除最久未使用的數據值,
  從而爲新的數據值留出空間。

進階:你是否能夠在 O(1) 時間複雜度內完成這兩種操做?

示例:

LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 該操做會使得關鍵字 2 做廢
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操做會使得關鍵字 1 做廢
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/lru-cache
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。

給定方法體:

/**
 * @param {number} capacity
 */
var LRUCache = function(capacity) {

};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {

};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {

};

/**
 * Your LRUCache object will be instantiated and called as such:
 * var obj = new LRUCache(capacity)
 * var param_1 = obj.get(key)
 * obj.put(key,value)
 */

答案(詳細看註釋,更多不解釋):

/**
 * @name LRU算法
 * @param {number} capacity 緩存容量
 */
const LRUCache = function(capacity) {
  // 設置哈希映射
  this.hash = {};

  // 設置 key 值列表
  this.keys = [];

  // 設置 length 長度
  this.capacity = capacity;

  // 讀取數據:key - 關鍵字(輸出 value 值,沒有返回 -1)
  this.get = (key) => {

    // 查找當前 hash 是否有對應的映射
    if (this.hash[key]) {

      // 將這個鍵刪除並添加到數組頭部
      this.keys.splice(this.keys.indexOf(key), 1);
      this.keys.unshift(key);

      // 若是有返回對應值
      return this.hash[key];
    } else {
      // 若是沒有返回 -1
      return -1;
    }
  };

  // 寫入數據:key - 關鍵字;value - 值(不須要輸出)
  this.put = (key, value) => {
    
    // 查找這個 key 是否存在於當前列表
    const index = this.keys.indexOf(key);

    // 若是存在,那就刪除
    if (index > -1) {
      const outKey = this.keys.splice(index, 1);
      delete this.hash[outKey];
    } else if (index !== -1 || this.keys.length >= this.capacity) {
      // 若是不存在且當前數組長度超限,則推出最末尾的
      const outKey = this.keys.pop();
      delete this.hash[outKey];
    }

    // 最後插入鍵值對
    this.hash[key] = value;
    this.keys.unshift(key);
  };
};

const cache = new LRUCache(2);

cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1));       // 返回  1
cache.put(3, 3);    // 該操做會使得關鍵字 2 做廢
console.log(cache.get(2));       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操做會使得關鍵字 1 做廢
console.log(cache.get(1));       // 返回 -1 (未找到)
console.log(cache.get(3));       // 返回  3
console.log(cache.get(4));       // 返回  4

jsliang 的文檔庫由 梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。<br/>基於 https://github.com/LiangJunrong/document-library 上的做品創做。<br/>本許可協議受權以外的使用權限能夠從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處得到。
相關文章
相關標籤/搜索