实现 memo 和 memoize-one | 刷题打卡

1,024 阅读1分钟

题目描述

image.png
题目地址

思路分析

题目考察实现 memo 缓存函数,例如 React.memo(functionalComponent) 浅比对前后函数参数 props 的值,如果相同就不会执行函数。
需要定义一个闭包函数,闭包变量中存放 props,执行函数中判断变量中是否含有 props

function memo(fn) {
    const map = new Map();
    
    return function (...args) {
       // 取 key
      if (map.has(args)) {
          return map.get(args);
      }
      
      // 赋值 key
      map.set(args, fn(...args));
      return fn(...args);
    }
}

做到这一步,基本上实现了缓存函数,题目中还有两个要求还需要满足:

  • 如果 memo 函数有第二个参数 callback 缓存的 key 为回调函数的返回值
  • 绑定 this
function memo(fn, resolver) {
    const map = new Map();
    
    return function (...args) {
      // map 的 key 是引用类型会取不到值,所以 args.join() 一下
      const key = resolver ? resolver(...args) : args.join('_');
       // 取 key
      if (map.has(key)) {
          return map.get(key);
      }
      
      // 赋值 key
      const cache = fn.call(this, ...args)
      map.set(key, cache);
      return cache;
    }
}

// test1
function add(a, b) {
  return a + b;
}
const memod = memo(add);

console.log(memod(1, 2));
console.log(memod(1, 2));

// test2
function funcThis(b){
  return `${this.a}_${b}`;
}
const memoed = memo(funcThis);
const a = { a: 1, memoed }; // 1_2

至此,我们完成了 memo() 但是如果无限量使用 cache 会导致内存不足,所以在 memo 的基础上实现 memoize-one 仅缓存上一次的结果。 map 最多只能存在两个 map 对象,只需要在添加之前判断 map.size > 1 的情况删掉第一个缓存对象即可

// memoizeOne
if (map.size > 1) {
  map.delete(map.keys().next.value);
}

AC代码

/**
 * @param {Function} func
 * @param {(args:[]) => string }  [resolver] - cache key generator
 */
function memo(func, resolver) {
  // your code here
  const map = new Map();

  return function (...args) {
    const key = resolver ? resolver(...args) : args.join('_');
    if (map.has(key)) {
      console.log('is memoize', args);
      return map.get(key);
    }

    const cache = func.call(this, ...args)
    map.set(key, cache);
    return cache;
  }
}

总结

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情