Javascript では、次のような関数の結果をキャッシュする方法はありますか?
- a)。計算コストが高い。
- b)。複数回呼び出されます。
たとえば、頻繁に呼び出される再帰階乗関数を考えてみましょう。通常、次のような別の配列を作成し、facotrialResults = [];
計算時に結果を追加しfactorialResults[x] = result;
ますが、グローバル名前空間に新しい変数を追加することなく、このキャッシュを実現するより良い方法はありますか?
Javascript では、次のような関数の結果をキャッシュする方法はありますか?
たとえば、頻繁に呼び出される再帰階乗関数を考えてみましょう。通常、次のような別の配列を作成し、facotrialResults = [];
計算時に結果を追加しfactorialResults[x] = result;
ますが、グローバル名前空間に新しい変数を追加することなく、このキャッシュを実現するより良い方法はありますか?
キャッシュする関数にハッシュを添付できます。
var expensive_fn = function(val) {
var result = arguments.callee.cache[val];
if(result == null || result == undefined) {
//do the work and set result=...
arguments.callee.cache[val]=result;
}
return result;
}
expensive_fn.cache = {};
これには、関数が副作用のない1-1関数である必要があります。
アンダースコアライブラリを環境に組み込むことを検討できます。メモ化機能など、さまざまな用途に役立ちます
計算結果をキャッシュすることにより、特定の関数をメモします。実行速度の遅い計算を高速化するのに役立ちます。オプションのhashFunctionが渡された場合、元の関数の引数に基づいて、結果を格納するためのハッシュキーを計算するために使用されます。デフォルトのhashFunctionは、メモ化された関数の最初の引数をキーとして使用します。
var fibonacci = _.memoize(function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
});
新しい配列にグローバル名前空間を設定するのではなく、キャッシュされた結果が関数に関連付けられるように、独自の関数プロパティを定義できます。
function factorial(n) {
if (n > 0) {
if (!(n in factorial)) // Check if we already have the result cached.
factorial[n] = n * factorial(n-1);
return factorial[n];
}
return NaN;
}
factorial[1] = 1; // Cache the base case.
これに関する唯一の問題は、結果がキャッシュされているかどうかを確認するオーバーヘッドです。ただし、チェックの複雑さが問題の再計算よりもはるかに低い場合は、それだけの価値があります。
キャッシュの使用
それは一般的な解決策です
// wrap cache function
var wrapCache = function(f, fKey){
fKey = fKey || function(id){ return id; };
var cache = {};
return function(key){
var _key = fKey(key);
if (!cache[_key]){
cache[_key] = f(key);
};
return cache[_key];
};
};
// functions that expensive
var getComputedRGB = function(n){
console.log("getComputedRGB called", n) ;
return n * n * n;
};
// wrapping expensive
var getComputedRGBCache = wrapCache(getComputedRGB, JSON.stringify);
console.log("normal call");
console.log(getComputedRGB(10));
console.log(getComputedRGB(10));
console.log(getComputedRGB(10));
console.log(getComputedRGB(10));
// compute 4 times
console.log("cached call") ;
console.log(getComputedRGBCache(10));
console.log(getComputedRGBCache(10));
console.log(getComputedRGBCache(10));
console.log(getComputedRGBCache(10));
// compute just 1 times
// output
=> normal call
getComputedRGB called 10
1000
getComputedRGB called 10
1000
getComputedRGB called 10
1000
getComputedRGB called 10
1000
=> cached call
getComputedRGB called 10
1000
1000
1000
1000