记忆函数必须定义为变量吗?

Must memoized functions be defined as variables?

我刚刚问了这个问题 (),我得到了一个很好的答案...但是!只是为了更多地了解 JavaScript,我想知道是否可以用这种风格编写 momoized 函数:

function main () {
    function memoized_f(){
        //memoizing code
    }
}

编辑:请注意我不是在问上面的代码有什么区别,我是在问是否可以记住第二个代码!

那么,如何重写呢?

function main() {
  var create_node = (function() {
    var memo;
    console.log("memo: " + memo);
    console.log("create_node")

    function f() {
      var value;
      if (memo) {
        value = memo.cloneNode();
        console.log("clone node");
        console.log(value);
      } else {
        var value = document.createElement("div");
        value.innerHTML = "hello";
        console.log("new node");
        console.log("value: " + value);
        memo = value;
      }
      return value;
    }
    return f;
  })();
  var collection = [];
  for (var i = 0; i < 10; i++) {
    collection.push(create_node());
  };
  // Display results
  for (var i = 0; i < 10; i++) {
    console.log(i + ". " + collection[i]);
  }
}
main();

您实际记忆的函数是f(function(){ ... })() IIFE wrapping 仅仅提供了一个额外的闭包层来隐藏变量 memo 以便它只对 f.

可见

重复一遍:(function(){...})() 表达式 不是 你的记忆函数。包装限制了内部变量的可见性,最终 returns 你的记忆函数 f,它是在它内部定义的。如果您可以将 memo 暴露给 main 中的其他代码并且不限制其仅对记忆函数的可见性,您可以完全消除 IIFE 包装并简单地将 f 重命名为 create_node:

function main() {
    var memo;

    function create_node() {
      var value;
      if (memo) { value = memo.cloneNode(); }
      else {
        var value = document.createElement("div");
        value.innerHTML = "hello";
        memo = value;
      }
      return value;
    }

  // use `create_node` as originally done
  // NOTE that other code can manipulate `memo` now, though!
}
main();

如果愿意,您可以通过函数声明而不是 IIFE 提供闭包包装:

function createMemoizedFunc() {
    var memo;

    function f() {
      var value;
      if (memo) { value = memo.cloneNode(); }
      else {
        var value = document.createElement("div");
        value.innerHTML = "hello";
        memo = value;
      }
      return value;
    }
    return f;
}
var create_node = createMemoizedFunc();

由于 javascript 中的函数是一个对象,您可以只使用该函数来记忆值。我认为在 fib example 中更有意义,但这是您的原始 post。

function main() {
  // memoizing function
  function create_node() {
    var value;
    // read from memo on function object
    if (create_node.memo) {
      value = create_node.memo.cloneNode();
      value.innerHTML = 'cloned';
      console.log("clone node");
      console.log(value);
    } else {
      var value = document.createElement("div");
      value.innerHTML = "hello";
      console.log("new node");
      console.log("value: " + value);
      // retain memo on the function object
      create_node.memo = value;
    }
    return value;
  }

  var collection = [];
  for (var i = 0; i < 10; i++) {
    collection.push(create_node());
  };
  // Display results
  for (var i = 0; i < 10; i++) {
    console.log(i + ". " + collection[i]);
    document.getElementById('container').appendChild(collection[i]);
  }
}

main();
<div id="container"></div>