github地址:https://github.com/alexreardon/memoize-one

与其他记忆库不同,记忆库只记住最新的参数和结果。无需担心缓存破坏机制,如maxAge、maxSize、exclusions等,这些机制可能会导致内存泄漏。memorize one只需记住最后一个参数,如果下一次用相同的参数调用函数,那么它将返回以前的结果。

使用原因

  • 有时候组件的更新并不是因为从服务器拿来的这一段数据结构发生变化造成的(组件中的其他部分更新造成的),但是这一段很重的逻辑因为是写在 render 中的,所以不可避免的在每次 render 会调用一次。如果这段逻辑在两次调用的时候,输入参数是一样的,那么输出结果必然一样,所以再次计算是一种十分浪费资源的行为。
  • 根据memoize-one名字中的one可以知道,这个库的每个实例都缓存了一个结果,下一次不同的结果将覆盖上一次的。虽然只能缓存一个数据,但是用到合适的地方却能发挥很大的作用。
  1. import memoizeOne from 'memoize-one';
  2. const add = (a, b) => a + b;
  3. const memoizedAdd = memoizeOne(add);
  4. memoizedAdd(1, 2); // 3
  5. memoizedAdd(1, 2); // 3
  6. // Add 函数并没有执行: 前一次执行的结果被返回
  7. memoizedAdd(2, 3); // 5
  8. // Add 函数再次被调用以获得新的结果
  9. memoizedAdd(2, 3); // 5
  10. // Add 函数并没有执行: 前一次执行的结果被返回
  11. memoizedAdd(1, 2); // 3
  12. // Add 函数再次被调用以获得新的结果
  13. // 虽然之前调用过
  14. // 但是不是上一次调用的,所以结果丢失了

方法说明

  • memoizeOne(resultFn, isEqual)接收一个结果函数和一个对比函数,对比函数为空则默认使用===来进行入参的比较。
    简单来讲就是,memoizeOne()在原来resultFn()函数外面包了一层,返回一个函数,然后每次调用的时候看新入参newArgs是否和上一次的入参lastArgs一致,参数不变,则直接返回缓存的结果,否则重新执行resultFn(newArgs),缓存新结果。
  • isEqual函数
    因为对相等的理解,不同场景不一样,而且参数有时候是复杂的对象,所以我们不能仅仅通过比较操作符 == 或者 === 来判断。memoize-one 允许用户自定义传入判断是否相等的函数,比如我们可以使用 lodash 的 isEqual 来判断两次参数是否相等。
    ```javascript import memoizeOne from ‘memoize-one’; import deepEqual from ‘lodash/isEqual’;

const identity = x => x;

const defaultMemoization = memoizeOne(identity); const customMemoization = memoizeOne(identity, deepEqual);

const result1 = defaultMemoization({foo: ‘bar’}); const result2 = defaultMemoization({foo: ‘bar’});

result1 === result2 // false - 索引不同

const result3 = customMemoization({foo: ‘bar’}); const result4 = customMemoization({foo: ‘bar’});

result3 === result4 // true - 参数通过 lodash 的 isEqual 判断是相等的 ```

参考资料

React 常用依赖 - 简书
《记忆化技术memoize-one》 | Leon’s Blog