函数式编程之记忆

函数式编程之记忆 是一种时间换空间的方法,用牺牲空间的复杂度来换取时间的复杂度

字符串连接

function f() {
  var s = arguments.length + Array.prototype.join.call(arguments);
  console.log(s);
};
复制代码

这里使用的是Array.prototype.join方法进行字符串连接 返回的是连接的结果

接下来,写一个具有记忆的函数

// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cacho = {}; // 定义一个用于保存值的私有变量
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments, ',');
    if (key in cacho) 
      return cacho[key];
    else
      return cacho[key] = f.call(this, arguments);
  };
}
复制代码

这是一个具有记忆的函数,用数组的长度和数组合并后组成的字符串作为属性名,进行保存,如果这个值存在则直接进行保存,如果值不存在则进行保存并返回(因为赋值语句会返回右值,所以return语句后无需再跟进行返回值的语句)

使用调试函数对其进行修改


// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cacho = {}; // 定义一个用于保存值的私有变量
  console.log(cacho);
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments, ',');
    console.log(key);
    if (key in cacho) {
      console.log(cacho[key]);
      return cacho[key];
    }
    else {
      console.log(f.call(this,arguments));
      return cacho[key] = f.call(this, arguments);
    };
  };
}
复制代码

这样就更加的明显了

使用这个函数

返回两个整数的最大公约数 欧几里得算法

[由欧几里得最先发现,一个用于计算最大公因数的算法][1]

function gcd(a, b) {
  var t;  // 用于保存中间变量
  if(a < b)  // 确保 a >= b
    t = a, a = b, b = t; 
  
  while(t != 0)
    t = a % b, a = b, b = t;
  return a;
}
复制代码

利用欧几里得算法写的求两个数的最大公因数,运行一下

gcd(85, 187);
17
复制代码

计算结果正确,使用刚刚实现的具有记忆功能的高阶函数,将函数传进去,生成了一个新的函数

var functiongcd = memorize(gcd);
Object {  }
复制代码

使用这个函数 好吧。莫名进行死循环了。

Error: Script terminated by timeout at:
gcd@Scratchpad/1:35:9
memorize/<@Scratchpad/1:24:27
@debugger eval code:1:1
复制代码

没办法继续排查错误

排查错误

// 这是一个用于返回f()的带有记忆功能的函数
function memorize(f) {
  var cache = {}; 
console.log(cache);
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments);
   console.log(key);
    if (key in cache) {
      console.log(cache[key]);
      return cache[key];
    }
    else {
      console.log(f.apply(this,arguments));
      return cache[key] = f.apply(this, arguments);
    };
  };
}

复制代码

这个函数依旧写错了,call只能传入一个值,而apply能传入多个值

继续运行

gcdmemo(85, 187);
285,187 Scratchpad/1:17:4
17 Scratchpad/1:23:7
17
复制代码

其中第一个Scratchpad/1:17:4返回指代的是

    if (key in cache) {
      console.log(cache[key]);
      return cache[key];
    }
复制代码

其中第二个Scratchpad/1:23:7返回指代的是

      return cache[key] = f.apply(this, arguments);
复制代码

好啦,非常明显,第一步是先将值缓存进入其私有变量,即保存进入闭包内部,然后第二个是发现这个值已经保存过了直接输出

(^o^)/, js的记忆折腾完毕~ [1]: https://zh.wikipedia.org/wiki/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95

转载于:https://juejin.im/post/5b4c886df265da0f793a63ef

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值