memoize-one源码浅析

作用:同一个函数,在多次调用时,通过比较当前和上一次两者的参数是否相等来减少函数的请求次数,从而提高性能;

memoize-one其核心主要使用闭包的工作原理,简单的说就是将内部的函数存在内存中 ,那我们就由简到难,通过举一个简单的例子来介绍memoize-one的使用场景,并逐步深入下去:

未使用memoize-one,called被打印了两次:

const canThrow = (name) => {
  console.log('called');  // 执行了两次
  return { name };
};
 
const value1 = canThrow('Alex');
const value2 = canThrow('Alex');

使用memoize-one,called只打印了一次:

const canThrow = (name) => {
  console.log('called');  // 执行了两次
  return { name };
};
 
const memoized = memoizeOne(canThrow);
 
const value1 = canThrow('Alex');
const value2 = canThrow('Alex');

下面我们看一下memoize-one的源码:

    (function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.memoizeOne = factory());
}(this, function () { 'use strict';
  
  // 浅比较两次调用的参数
  function areInputsEqual(newInputs, lastInputs) {
      // 判断两者长度[入参的个数]是否相等,如果不等的话,则返回false, 就没必要再继续比较了
      if (newInputs.length !== lastInputs.length) {
          return false;
      }
      // 判断两次入参[一一对应]的值是否相等,如果有一个不相等,证明入参是不一样的,返回false
      for (var i = 0; i < newInputs.length; i++) {
          if (newInputs[i] !== lastInputs[i]) {
              return false;
          }
      }
      return true;
  }

  function memoizeOne(resultFn, isEqual) {
      /**
       * @param {function} isEqual
       * isEqual可以是一些深比较的方法,比如lodash.isequal
      */
      // isEqual判断isEqual是否有传, 未传使用 areInputsEqual
      if (isEqual === void 0) { isEqual = areInputsEqual; }
      var lastThis;
      var lastArgs = [];
      var lastResult;
      var calledOnce = false;
      function memoized() {
          var newArgs = [];
          // 将arguments遍历复制给一个新的变量
          for (var _i = 0; _i < arguments.length; _i++) {
              newArgs[_i] = arguments[_i];
          }
          // 1. calledOnce、lastThis目的是判断memoized方法是第二次(多次)被调用 2. isEqual(newArgs, lastArgs)判断入参如果相等的话,就没必要再去调用resultFn这个函数了
          if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) {
              return lastResult;
          }
          // 将参数整合array, 再通过apply去调用函数
          lastResult = resultFn.apply(this, newArgs);
          calledOnce = true;
          lastThis = this;
          lastArgs = newArgs;
          return lastResult;
      }
      return memoized;
  }

  return memoizeOne;

}));

首先memoize-one接受两个参数, 第一个参数是要执行的函数,第二个参数(非必填)可以是自定义比较值是否相等的一些方法;

1. 我们在通过memoizeOne(canThrow)调用时,其实返回的是一个未被执行的函数;

2. canThrow('Alex') 第一次被调用时,会通过resultFn.apply(this, newArgs) 得出lastResult的值返回出去;

3. canThrow('Alex') 第二次(多次)被调用时,

if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) {
   return lastResult;
}

这个判断条件会进行比较,如果条件成立,则证明当前和上一次的参数是一样的,就会把上一次的结果返回出去,而不执行resultFn这个函数;

这样我们就基本清楚了memoize-one的工作原理;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值