function memoize(f, serializer = simpleSerializer) {
  const uidF = goog.getUid(f);
  const keyFn = ([that, ...args]) => serializer(uidF, args);
  const valueFn = ([that, ...args]) => f.apply(that, args);

  /**
   * @this {Object} The object whose function is being wrapped.
   * @param {...*} args
   * @return {?} the return value of the original function.
   */
  const memoizedFn = function(...args) {
    if (memoize.ENABLE_MEMOIZE) {
      const cacheKey = this || goog.global;
      let cache = MODULE_LOCAL_CACHE.get(cacheKey);
      if (!cache) {
        cache = {};
        MODULE_LOCAL_CACHE.set(cacheKey, cache);
      }
      return reflect.cache(cache, [this, ...args], valueFn, keyFn);
    } else {
      return f.apply(this, args);
    }
  };
  return memoizedFn;
}
Decorator around functions that caches the inner function's return values.

To cache parameterless functions, see goog.functions.cacheReturnValue.

@param {Function} f The function to wrap. Its return value may only depend
    on its arguments and 'this' context. There may be further restrictions
    on the arguments depending on the capabilities of the serializer used.
@param {function(number, !IArrayLike<?>): string=} serializer A function to
    serialize f's arguments. It must have the same signature as
    goog.memoize.simpleSerializer. It defaults to that function.
@return {!Function} The wrapped function.