Javascript,设计一个记忆函数

78 阅读1分钟

一.设计思路

1.思考:

创建一个记忆函数,考虑到利用闭包完成,每次函数执行完毕后应该缓存当次函数的传入参数以及执行结果。所以我在在设计函数内部的时候,使用map来完成函数的映射(map可以用function作为key),还考虑到相同函数可能,可能存在传入参入不同的调用,这就意味着map的value不能单一的,必须可以存储多个调用的映射,所以map中value考虑使用数组来存储调用详情,思考完毕,完善代码:

function memoizeFunction(fn) {
  let targetMap = new Map()
  return function() {
    let args = Array.from(arguments)
    // 设置目标返回为null
    let  targetItem = null
    // 如果目标函数已经存在
    if (targetMap.has(fn)) {
      let target = targetMap.get(fn).get('target')
      // 查找目标函数:是否存在参数完全相等的调用
      targetItem = target.find(item => {
        let flag = true
        // 如果参数长度相等
        if (item.args.length === args.length) {
          // 判断参数是否全等
          args.find((arg, index) => {
            if (arg !== item.args[index]) {
              flag = false
              return false
            }
          })
        }else {
          flag = false
        }
        return flag
      })
      // 如果目标函数不存在
      if(!targetItem){
        // 创建目标函数
        targetItem = {
          args: args,
          val: fn(...arguments),
          callTimes:target.length+1
        }
        // 将目标函数添加到目标函数数组中
        target.push(targetItem)
      }
    }else {
      // 如果目标函数不存在
      let map = new Map()
      // 创建目标函数
      targetItem = {
        // 参数
        args: args,
        // 返回值
        val: fn(...arguments),
        // 调用次数
        callTimes:1
      }
      // 将目标函数添加到目标函数数组中
      let arr = [targetItem]
      // 将目标函数数组添加到目标函数map中
      map.set('target',arr)
      // 将目标函数map添加到目标函数map中
      targetMap.set(fn,map)
    }
    // 返回目标函数的值
    return targetItem.val
  }
}

2.实际使用

let test = memoizeFunction((a, b) => {
  console.log('执行了')
  return a + b
})
  console.log(test(1,2))
  console.log(test(1,2))
  console.log(test(2,2))
  console.log(test(2,3))
  //   打印输出:
  //   执行了
  //   3
  //   3
  //   执行了
  //   4
  //   执行了
  //   5