【问题标题】:Function to cache its argument's return value缓存其参数返回值的函数
【发布时间】:2019-06-01 20:40:58
【问题描述】:

我想编写一个函数once,它接受一个回调作为输入并返回一个函数。第一次调用返回的函数时,它应该调用回调并返回该输出。如果再次调用它,它不会再次调用回调,而是简单地返回第一次调用时的输出值。

以下是我尝试做的。但我没有得到预期的结果。我需要理解这个概念。

function once(func) {
    let num; 
    function retFunc(x){
        num = func(x);
        return num;
    }
    return retFunc;
}

function addByTwo(input){
    return input + 2;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(4));  //should log 6
console.log(onceFunc(10));  //should log 6
console.log(onceFunc(9001));  //should log 6

【问题讨论】:

  • num 已经是很好的第一步,但你怎么记得它已经被称为第一次了?你总是覆盖num = func(x)
  • 仅供参考,这称为memoization

标签: javascript memoization


【解决方案1】:

不同的方法:覆盖对 func 的调用

没有标志,检查结果是否未定义或需要任何东西

function once(func) {
    let num;

    let internalFn = function(x) {
        num = func(x);
        internalFn = function(x) {
            return num;
        }
        return num;
    }

    function retFunc(x){
        return internalFn(x);
   }
      return retFunc;
  }

  function addByTwo(input){
    return input + 2;
  }

  var onceFunc = once(addByTwo);

  console.log(onceFunc(4));  //should log 6
  console.log(onceFunc(10));  //should log 6
  console.log(onceFunc(9001));  //should log 6

【讨论】:

    【解决方案2】:

    你应该只调用函数并分配num如果它是未定义的,否则你每次都覆盖它:

    function once(func) {
      let num;
    
      function retFunc(x) {
        num = (num === undefined) ? func(x) : num
        return num;
      }
      return retFunc;
    }
    
    function addByTwo(input) {
      return input + 2;
    }
    
    var onceFunc = once(addByTwo);
    
    console.log(onceFunc(4)); //should log 6
    console.log(onceFunc(10)); //should log 6
    console.log(onceFunc(9001)); //should log 6

    请注意,如果您传入的函数返回undefined,它将被多次调用。如果您需要处理这种情况,您可以设置一个标志来指示缓存值是否有效。

    【讨论】:

    • 哇,你在这里真的很有帮助,不是吗?难怪你有 36.8k 代表
    • @YangK 主要是失眠!
    【解决方案3】:

    您应该只在numundefined 时分配num = func(x) - 也就是说,在第一次调用retFunc 时:

    function once(func) {
      let num; 
      function retFunc(x){
        if (num === undefined) {
          num = func(x);
        }
        return num;
      }
      return retFunc;
    }
    
    function addByTwo(input){
      return input + 2;
    }
    
    var onceFunc = once(addByTwo);
    
    console.log(onceFunc(4));  //should log 6
    console.log(onceFunc(10));  //should log 6
    console.log(onceFunc(9001));  //should log 6

    但这不是一个有保证的通用解决方案 - 如果调用时传递的函数(在您的示例中为 addByTworesults 会怎样?然后,=== undefined 检查将不起作用。因此,最好设置一个标志或类似的东西,并在第一次调用回调时重新分配该标志:

    function once(func) {
      let num;
      let done = false;
      function retFunc(x){
        if (!done) {
          done = true;
          num = func(x);
        }
        return num;
      }
      return retFunc;
    }
    
    function returnsUndefinedOn1(input){
      return input === 1 ? undefined : input;
    }
    
    var onceFunc = once(returnsUndefinedOn1);
    
    console.log(onceFunc(1));
    console.log(onceFunc(10));
    console.log(onceFunc(9001));

    【讨论】:

    • 这是期望的行为 - 在1 的输入上,函数returnsUndefinedOn1 根据其名称返回undefined。对onceFunc 的进一步调用也将返回undefined,尽管使用参数other 而不是1
    • 请使用typeofundefined进行比较
    • @PierreArlaud 在任何远程合理的代码中,我认为都没有必要?许多全局对象可以重新定义,这并不意味着它们不应该被使用,这意味着不要重新分配它们。
    • @CertainPerformance typeof 如果未声明变量也不会触发异常。没有不使用 typeof 与 undefined 进行比较的情况是更好的选择。我对这件事的看法是,使用 typeof 是一个好习惯,“远程合理的代码”也不例外。
    • @PierreArlaud:在这种情况下,如果未声明变量,则获得异常是可取的,因为我们正在尝试测试我们知道的变量的值声明了,异常告诉我们变量名打错了代码。
    【解决方案4】:

    您缺少的是在第一次执行后删除原始函数。您应该通过以下方式修改您的代码:

    function once(func) {
      let num; 
      function retFunc(x){
          if (func)
              num = func(x);
          func = null;
          return num;
     }
        return retFunc;
    }
    
    function addByTwo(input){
      return input + 2;
    }
    
    var onceFunc = once(addByTwo);
    
    console.log(onceFunc(4));  //should log 6
    console.log(onceFunc(10));  //should log 6
    console.log(onceFunc(9001));  //should log 6
    

    这样你在第一次使用后删除函数,你只是保留结果。

    【讨论】:

    • 另外我想说这种方式比依赖结果更好,因为函数不需要总是返回一些东西。它可能会返回 undefined,但我们仍然只想运行一次。
    【解决方案5】:

    这是你的问题

    function retFunc(x){
            num = func(x);
            return num;
        }
    

    你总是打电话给func(x)。在调用func(x)之前添加一个if条件来检查num是否为undefined

    【讨论】:

    • 嗨,通过添加 if 条件来检查 num 是否未定义,我的代码现在正在运行。
    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 2012-08-03
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2021-10-10
    相关资源
    最近更新 更多