欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用JavaScrip實(shí)現(xiàn)一個(gè)記憶函數(shù)

 更新時(shí)間:2024年11月27日 10:14:04   作者:JYeontu  
在編程的世界里,性能優(yōu)化始終是一個(gè)重要的話題,今天,我們將一起來實(shí)現(xiàn)一個(gè)實(shí)用的記憶函數(shù),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一

說在前面

在編程的世界里,性能優(yōu)化始終是一個(gè)重要的話題。今天,我們將一起來實(shí)現(xiàn)一個(gè)實(shí)用的記憶函數(shù)(簡(jiǎn)單來說,就是同樣的入?yún)?,只?huì)在第一次調(diào)用指定函數(shù)獲取結(jié)果,后續(xù)則可以直接獲取到第一次計(jì)算的結(jié)果返回),它能夠顯著提升函數(shù)調(diào)用的效率,特別是在處理重復(fù)計(jì)算的場(chǎng)景中。

需求

現(xiàn)給定一個(gè)函數(shù) fn ,返回該函數(shù)的一個(gè) 記憶化 版本。

一個(gè) 記憶化 的函數(shù)是一個(gè)函數(shù),它不會(huì)被相同的輸入調(diào)用兩次。而是會(huì)返回一個(gè)緩存的值。

函數(shù) fn 可以是任何函數(shù),對(duì)它所接受的值類型沒有任何限制。如果兩個(gè)輸入值在 JavaScript 中使用 === 運(yùn)算符比較時(shí)相等,則它們被視為相同。

示例1

輸入:

getInputs = () => [[2,2],[2,2],[1,2]]
fn = function (a, b) { return a + b; }

輸出:

[{"val":4,"calls":1},{"val":4,"calls":1},{"val":3,"calls":2}]

解釋:

const inputs = getInputs();
const memoized = memoize(fn);
for (const arr of inputs) {
  memoized(...arr);
}

對(duì)于參數(shù)為 (2, 2) 的輸入: 2 + 2 = 4,需要調(diào)用 fn() 。

對(duì)于參數(shù)為 (2, 2) 的輸入: 2 + 2 = 4,這些輸入之前已經(jīng)出現(xiàn)過,因此不需要再次調(diào)用 fn()。

對(duì)于參數(shù)為 (1, 2) 的輸入: 1 + 2 = 3,需要再次調(diào)用 fn(),總共調(diào)用了 2 次。

示例2

輸入:

getInputs = () => [[{},{}],[{},{}],[{},{}]] 
fn = function (a, b) { return a + b; }

輸出:

[{"val":{},"calls":1...

解釋:

將兩個(gè)空對(duì)象合并總是會(huì)得到一個(gè)空對(duì)象。盡管看起來應(yīng)該緩存命中并只調(diào)用一次 fn(),但是這些空對(duì)象彼此之間都不是 === 相等的。

示例3

輸入:

getInputs = () => { const o = {}; return [[o,o],[o,o],[o,o]]; }
fn = function (a, b) { return ({...a, ...b}); }

輸出:

[{"val":{},"calls":1},{"val":{},"calls":1},{"val":{},"calls":1}]

解釋:

將兩個(gè)空對(duì)象合并總是會(huì)得到一個(gè)空對(duì)象。因?yàn)閭魅氲拿總€(gè)對(duì)象都是相同的,所以第二個(gè)和第三個(gè)函數(shù)調(diào)用都會(huì)命中緩存。

代碼實(shí)現(xiàn)

1、入?yún)⑻幚?/h3>

要避免重復(fù)計(jì)算相同入?yún)ⅲ俏覀兙托枰獙⒚看斡?jì)算的入?yún)⒂涗浧饋?,但是入?yún)?huì)有多個(gè),我們還需要將所有入?yún)⒁灿涗浧饋?,那么怎么將多個(gè)入?yún)⑥D(zhuǎn)成一個(gè)key呢?

首先我們先簡(jiǎn)化一下,如果入?yún)⒍际亲址脑捨覀儠?huì)怎么進(jìn)行處理?

沒錯(cuò),都是字符串的話我們可以直接使用連接符號(hào)將所有入?yún)⑦B接起來作為一個(gè)key。那么現(xiàn)在入?yún)?shù)據(jù)格式多種的情況我們應(yīng)該要怎么處理呢?

既然入?yún)⒍际亲址臅r(shí)候我們可以處理,那我們就給每一個(gè)入?yún)①x予一個(gè)專屬的id,如下圖:

const idMap = new Map();
const getId = (k) => {
  if (idMap.has(k)) {
    return idMap.get(k);
  }
  const size = idMap.size;
  idMap.set(k, size);
  return size;
};

這個(gè)函數(shù)用于為傳入的參數(shù)生成一個(gè)唯一的標(biāo)識(shí)符。它首先檢查 idMap 中是否已經(jīng)存在該參數(shù)對(duì)應(yīng)的標(biāo)識(shí)符,如果存在,則直接返回;如果不存在,就將當(dāng)前 idMap 的大小作為新的標(biāo)識(shí)符,并將參數(shù)與標(biāo)識(shí)符的映射關(guān)系存儲(chǔ)到 idMap 中。

因?yàn)檫@里的入?yún)⒖梢允侨我忸愋偷臄?shù)據(jù),所以我們這里不能直接用Object對(duì)象來記錄,可以使用Map來記錄。

const a = {aa:1};
const b = {};
const c = new Map();
b[a] = 1;
c.set(a,1);
console.log(b);
console.log(c);

這里我們得到的b為:

{
    "[object Object]": 1
}

c為:

new Map([
    [
        {
            "aa": 1
        },
        1
    ]
])

2、記錄入?yún)?/h3>

遍歷arguments,獲取到每一個(gè)入?yún)⒌膶賗d,最后使用-將所有id連接起來作為一組入?yún)⒌?code>key,將計(jì)算得到的值作為value保存。

const arr = [];
for (const element of arguments) {
  arr.push(getId(element));
}
const key = arr.join("-");
if (!valMap.has(key)) {
  valMap.set(key, fn(...arguments));
}
return valMap.get(key);

3、完整代碼

/**
 * @param {Function} fn
 * @return {Function}
 */

function memoize(fn) {
  const idMap = new Map();
  const valMap = new Map();
  const getId = (k) => {
    if (idMap.has(k)) {
      return idMap.get(k);
    }
    const size = idMap.size;
    idMap.set(k, size);
    return size;
  };
  return function () {
    const arr = [];
    for (const element of arguments) {
      arr.push(getId(element));
    }
    const key = arr.join("-");
    if (!valMap.has(key)) {
      valMap.set(key, fn(...arguments));
    }
    return valMap.get(key);
  };
}

應(yīng)用場(chǎng)景

假設(shè)我們有一個(gè)復(fù)雜的對(duì)象,其中某個(gè)屬性的計(jì)算需要消耗大量資源,并且該屬性可能會(huì)被多次訪問。

const complexObject = {
  data: {
    // 大量復(fù)雜數(shù)據(jù)
  },
  getComputedProperty: memoize(function () {
    // 復(fù)雜的計(jì)算邏輯,例如遍歷 data 中的數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析
    return result;
  })
};

console.log(complexObject.getComputedProperty());
console.log(complexObject.getComputedProperty());

在第一次訪問 complexObject.getComputedProperty 時(shí),會(huì)執(zhí)行復(fù)雜的計(jì)算邏輯并緩存結(jié)果。后續(xù)再次訪問時(shí),直接返回緩存的結(jié)果,避免了重復(fù)計(jì)算,提高了整體性能。

到此這篇關(guān)于使用JavaScrip實(shí)現(xiàn)一個(gè)記憶函數(shù)的文章就介紹到這了,更多相關(guān)JavaScrip函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論