什么是 JavaScript 記憶化(Memoization)?
共 3673字,需瀏覽 8分鐘
·
2024-07-29 11:59
大廠技術(shù) 高級(jí)前端 Node進(jìn)階
點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)Node交流群
什么是 Memoization?
大廠技術(shù) 高級(jí)前端 Node進(jìn)階
點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)
回復(fù)1,加入高級(jí)Node交流群
Memoization(記憶化)是一種優(yōu)化技術(shù),主要用于加速計(jì)算機(jī)程序。它通過存儲(chǔ)耗時(shí)函數(shù)的計(jì)算結(jié)果,在相同輸入再次傳遞時(shí),直接返回緩存的結(jié)果,從而避免重復(fù)計(jì)算。
為什么需要 Memoization?
讓我們通過一個(gè)簡(jiǎn)單的例子來了解 Memoization 的必要性。
function square(num) {
return num * num;
}
console.log(square(2)); // 返回 4
console.log(square(9999999999999999)); // 這是一項(xiàng)耗時(shí)的計(jì)算
console.log(square(9999999999999999)); // 我們是否應(yīng)該為相同的輸入重新計(jì)算?
上面的函數(shù)對(duì)于較小的數(shù)字輸入計(jì)算非常快,但如果輸入是一個(gè)非常大的數(shù)字,如 9999999999999999,調(diào)用 square(9999999999999999) 兩次將會(huì)是一項(xiàng)耗時(shí)的計(jì)算,我們可以通過 Memoization 避免這種重復(fù)計(jì)算。
如何將上述函數(shù)轉(zhuǎn)換為 Memoized 函數(shù)?
function square(n) {
return n * n;
}
function memoizedSquare() {
let cache = {};
return function optimizedSquare(num) {
if (num in cache) {
console.log('從緩存中返回結(jié)果');
return cache[num];
} else {
console.log('計(jì)算平方');
const result = square(num);
cache[num] = result;
return result;
}
};
}
const memoSquare = memoizedSquare();
console.log(memoSquare(9999999999999999));
console.log(memoSquare(9999999999999999));
// 輸出:
// "計(jì)算平方"
// 1e+32
// "從緩存中返回結(jié)果"
// 1e+32
在這個(gè)例子中,我們創(chuàng)建了一個(gè) memoizedSquare() 函數(shù),該函數(shù)利用 JavaScript 的閉包和對(duì)象來實(shí)現(xiàn)緩存機(jī)制。我們檢查輸入數(shù)字是否已在緩存中,如果在則返回緩存結(jié)果,否則進(jìn)行計(jì)算并將結(jié)果存儲(chǔ)在緩存中。這種方法可以幫助我們避免不必要的耗時(shí)計(jì)算。
改進(jìn)的可重用 Memoize 函數(shù)
function memoize(callback) {
let cache = {};
return function(...args) {
const key = args.toString();
if (key in cache) {
console.log('從緩存中返回結(jié)果');
return cache[key];
} else {
console.log('計(jì)算結(jié)果');
const result = callback(...args);
cache[key] = result;
return result;
}
};
}
function multiply(a, b) {
return a * b;
}
const memoMultiplication = memoize(multiply);
console.log(memoMultiplication(10, 10));
console.log(memoMultiplication(10, 10));
// 輸出:
// "計(jì)算結(jié)果"
// 100
// "從緩存中返回結(jié)果"
// 100
這個(gè)通用的 memoize 函數(shù)可以應(yīng)用于任何需要緩存的函數(shù)。我們通過傳遞回調(diào)函數(shù)實(shí)現(xiàn)緩存機(jī)制,并在函數(shù)調(diào)用時(shí)檢查緩存以決定是返回緩存結(jié)果還是重新計(jì)算。
Memoization 技術(shù)的潛在缺點(diǎn)
-
增加內(nèi)存使用:由于 Memoization 需要緩存函數(shù)調(diào)用的結(jié)果,這可能會(huì)增加程序的內(nèi)存使用,特別是當(dāng)緩存變大時(shí)。使用 Memoization 時(shí)需要小心管理內(nèi)存。
-
緩存失效:如果 Memoized 函數(shù)的輸入隨時(shí)間變化(例如緩存的網(wǎng)絡(luò)請(qǐng)求結(jié)果每次返回不同的數(shù)據(jù)),需要謹(jǐn)慎管理緩存以確保其始終是最新的。有時(shí)管理緩存可能比值得計(jì)算要麻煩。
-
增加代碼復(fù)雜度:Memoization 會(huì)增加代碼的復(fù)雜度,特別是在需要處理邊緣情況或優(yōu)化緩存大小以提高性能時(shí)。需要權(quán)衡 Memoization 帶來的性能提升與其增加的復(fù)雜度及潛在的 bug。
結(jié)束
總之,Memoization 是一種強(qiáng)大的技術(shù),可以提高 JavaScript 代碼的性能,但并非適用于所有場(chǎng)景。在使用 Memoization 之前,請(qǐng)仔細(xì)考慮其潛在的好處和缺點(diǎn),確定它是否適合你的應(yīng)用程序。
Node 社群
我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
“分享、點(diǎn)贊、在看” 支持一波??
