你不知道的秘密之函数记忆思想优化代码

本文主要用于回顾复习和加深理解

  • 首先,递归思想在实现函数功能上十分方便,但是却十分耗费性能,比如下面这个例子
	// 递归求阶乘
	function jieCheng_1(num) {
		if (num <= 1) {
			return 1; // 递归的出口
		}
		return num * jieCheng_1(num - 1); // 递归
	}
  • 由递归的写法可发现,当num > 2时,计算出num的阶乘值所需要调用阶乘函数的次数为 : 本次调用一次 + 计算num-1的阶乘值所需要调用阶乘函数的次数

  • 所以,我们可以设计一个缓存空间,用来将算出来的阶乘值保存起来,比如我们算出来了num-1的阶乘,就将它保存到缓存空间,当计算num的阶乘时,只需要从缓存中读取num-1的阶乘值,并和num相乘即为计算结果

	// 递归求阶乘
	var cache = {}; // 缓存区
	function jieCheng_2(num) {
		var cacheItem = cache[num];
		if (cacheItem) {
	    	return cacheItem;
	    } else {
	    	return cache[num] = num <= 1 ? 1 : num * cache[num - 1];
	    }
	}
  • 我们继续优化,可以将缓存做成一个功能,利用闭包将缓存空间私有化
	/* 缓存函数 */
	function memory(fn) {
	  var cache = {}; // 私有化缓存结构
	  return function () {
	    var key = arguments[0],
	      cacheItem = cache[key];
	    if (cacheItem) {
	      return cacheItem;
	    } else {
	      return cache[key] = fn.apply(this, arguments);
	    }
	  }
	}
  • 我们比较下列三个函数在同等数量级的运行效率

    • jieCheng_1
    • jieCheng_2
    • memoryJieCheng
    console.time();
    jieCheng_1(10000);
    console.timeEnd();
    
    console.time();
    jieCheng_2(10000);
    console.timeEnd();
    
    console.time();
    memory(jieCheng_1)(10000);
    console.timeEnd();
    

    在这里插入图片描述

    • 但注意: 闭包会造成内存泄露(占用), 时间成本和空间成本需权衡
发布了49 篇原创文章 · 获赞 29 · 访问量 1897

猜你喜欢

转载自blog.csdn.net/Brannua/article/details/104734504