如何用 JavaScript 编写简单的 Memoization 函数代码?

什么是Memoization函数?

Memoization(记忆化)是一种优化技术,它可以缓存函数的结果,达到减少重复计算的目的。当使用相同的参数调用同一个函数时,它会从缓存中返回结果而不是重新计算。这种技术在计算量大、重复计算较多的函数中非常实用。

下面我们就来看看如何用JavaScript编写一个简单的Memoization函数。

实现Memoization函数的两种方法

方法一:闭包(Closure)

下面的函数代码就是用闭包实现Memoization函数的例子:

function memoize(func) {

var cache = {};

return function() {

var key = JSON.stringify(arguments);

if (cache[key]) {

console.log("从缓存中取得计算结果:");

console.log(cache[key]);

return cache[key];

} else {

console.log("进行计算并缓存结果:");

var val = func.apply(this, arguments);

cache[key] = val;

return val;

}

};

}

这段代码中,memoize函数返回了一个闭包函数,这个闭包函数引用了外部的cache变量。当调用返回的闭包函数时,先进行参数的序列化(将多个参数转换为一个字符串),然后检查缓存中是否存在这个参数的计算结果。如果存在,则直接返回缓存中的值;否则进行函数计算,并将结果存入缓存,然后才返回结果。

这种方法只适用于原始类型或序列化后的参数,不适合传递引用类型的参数。

方法二:Map

使用ES6的Map数据结构也可以实现Memoization函数。下面的代码就是用Map实现Memoization函数的例子:

function memoize(func) {

var cache = new Map();

return function() {

var key = JSON.stringify(arguments);

if (cache.has(key)) {

console.log("从缓存中取得计算结果:");

console.log(cache.get(key));

return cache.get(key);

} else {

console.log("进行计算并缓存结果:");

var val = func.apply(this, arguments);

cache.set(key, val);

return val;

}

};

}

这段代码中,memoize函数同样返回了一个闭包函数,这个闭包函数引用了外部的cache变量。当调用返回的闭包函数时,先进行参数的序列化(将多个参数转换为一个字符串),然后检查缓存中是否存在这个参数的计算结果。如果存在,则直接返回缓存中的值;否则进行函数计算,并将结果存入缓存,然后才返回结果。

这种方法适用于所有类型的参数,因为Map可以存储引用类型。

使用Memoization函数的例子

下面是使用Memoization函数的一个例子:

function fibonacci(n) {

if (n === 0) return 0;

if (n === 1) return 1;

return fibonacci(n - 1) + fibonacci(n - 2);

}

var memoizedFibonacci = memoize(fibonacci);

console.log(memoizedFibonacci(10));

console.log(memoizedFibonacci(10));

这段代码中,我们定义了一个递归函数fibonacci(n),它能够计算斐波那契数列的第n项。然后我们使用memoize函数创建一个新的函数,这个函数在调用fibonacci(n)时会缓存计算结果。最后我们分别调用memoizedFibonacci(10)两次,发现第二次调用时不再进行计算,而是直接从缓存中返回结果:

进行计算并缓存结果:

55

从缓存中取得计算结果:

55

结论

Memoization是一种非常实用的优化技术,它可以降低函数计算的成本,提高程序的运行效率。我们可以使用闭包或Map来实现Memoization函数,然后在需要进行重复计算的函数中使用这个函数。当然,Memoization函数并不是万能的,它也有一些局限性,需要我们在使用时加以注意。