谁能解释一下下面使用 JS 和记忆技术的代码中发生了什么

ra8*_*9fi 5 javascript memoization

如果有人能以简单的方式逐步解释这里发生的事情,那将非常有帮助。我知道memoize()正在缓存函数,但我需要更好的理解。谢谢你!

var memoize = function (f) {
  var cache = {};
  return function () {
    var str = JSON.stringify(arguments);
    cache[str] = cache[str] || f.apply(f, arguments);
    return cache[str];
  };
};

var mUser = memoize(function(x){
  return function() {
    return x;
  };
});

var x = mUser(1);
var y = mUser(2);
console.log(x());  //1
console.log(y());  //2
Run Code Online (Sandbox Code Playgroud)

编辑:我保留原件以供记录。但发布修改后的代码和我对它的理解。如果我是对还是错,我需要意见以及对其中任何一个的一些解释。

var memoize = function (injected) {
  var cache = {};
  return function closure_with_access_to_cache () {
    var str = JSON.stringify(arguments);
    cache[str] = cache[str] || injected.apply(injected, arguments);
    console.log(cache);
    return cache[str];
  };
};

var memoizeUser = memoize (function injected(a) {
  return function closure_with_access_to_a () {
    return a;
  };
});

memoizeUser();
Run Code Online (Sandbox Code Playgroud)

让我们尝试回溯过去的事情。

首先,当memoizeUser();语句被执行时,它代表什么memoizeUser或者首先调用哪个函数?

var memoizeUser = ... 是一个函数表达式,意味着它没有被提升。

所以,memoize被称为。

但是,var memoize = ...也是一个函数表达式。仔细看,它是一个闭包,接收调用时closure_with_access_to_cache传递给它的参数。memoizeUser

closure_with_access_to_cache第一次里面这个cache是空的,所以injected.apply(injected, arguments)被执行并得到另一个闭包closure_with_access_to_a作为返回值。该值被存储cache然后返回。因此,memoizeUser实际上变得closure_with_access_to_a等于a传递给 的值memoizeUser

让我们看一些调用和日志。

console.log(memoizeUser());
{ '{}': [Function: closure_with_access_to_a] }
[Function: closure_with_access_to_a]
Run Code Online (Sandbox Code Playgroud)

缓存键是空对象,因为没有任何内容作为参数传递给memoizeUser()memoizeUser()返回closure_with_access_to_a记录的函数。

console.log(memoizeUser()());
{ '{}': [Function: closure_with_access_to_a] }
undefined
Run Code Online (Sandbox Code Playgroud)

memoizeUser()返回被调用并记录为 undefined 的函数closure_with_access_to_a,它是 的值,a因为没有任何内容传递给memoizeUser

memoizeUser(1);
{ '{"0":1}': [Function: closure_with_access_to_a] }
Run Code Online (Sandbox Code Playgroud)

与上面类似,除了a值为 1。

console.log(memoizeUser(1)());
{ '{"0":1}': [Function: closure_with_access_to_a] }
1
Run Code Online (Sandbox Code Playgroud)

与上面类似,除了a值为 1。

Pau*_*aul 1

因此,本质上,它的作用是确保对于传递给它的任何给定参数集,任何给定函数只会执行一次。

当为给定函数执行 memoize 函数时,它将返回一个在上下文中具有该缓存的新函数。它所做的第一件事是创建参数对象的 JSON 字符串表示形式,以用作该特定结果的唯一键。

然后,它使用空合并运算符将该缓存值设置为其自身(如果已存在)或应用了这些参数的注入函数的结果。

如果您实际上命名了您正在使用的所有函数,这会更有意义:

function memoize(injectedFunction) {
  var cache = {};
  return function memoizedFunction() {
    // 'arguments' here is the arguments object for memoizedFunction.
    var cacheKey= JSON.stringify(arguments);

    // This is a logical OR which is null coalescing in JS. If cache[str] 
    // is null or undefined, the statement proceeds to call injectedFunction.apply. 
    // If it's not, then it returns whatever is stored there.
    cache[cacheKey] = cache[cacheKey] || injectedFunction.apply(injectedFunction, arguments);  
    return cache[cacheKey];
  };
};
Run Code Online (Sandbox Code Playgroud)

因此,本质上,考虑注入一个简单的加法函数:

function add(a, b) { return a + b; }

var memoizedAdd = memoize(add);

console.log(memoizedAdd(1, 2));
Run Code Online (Sandbox Code Playgroud)

此时,memoizedAdd 使用参数 1、2 运行。这会创建一个 、 的 cacheKey "{\"0\": 1, \"1\": 2}",然后设置cache[cacheKey] = add.apply(add, [1 ,2])(有效地,当然在内部它会将“add”视为“injectedFunction”。

下次运行 memoizeAdd(1,2) 时,您会从缓存中获得与 3 相同的结果,而无需再次运行 add() 函数。

希望一切都有意义。