【问题标题】:Only allowing a function to run n times with wrapper function只允许一个函数使用包装函数运行 n 次
【发布时间】:2019-07-17 12:27:32
【问题描述】:

我需要创建一个包装函数来调用具有给定次数num 的函数multiply 以允许执行multiplynTimes(num,2) 然后分配给runTwice -- runTwice 可以是调用nTimes 函数的任何函数,该函数给出不同的num 输入--

就我而言,为简单起见,我只允许它运行 2 次 num=2 如果我们第一次和第二次运行runTwice 函数,它将返回multiply 函数使用multiply 的输入计算的结果。第二次之后的任何调用都不会运行multiply 函数,但会返回multiply 函数的最新结果。

这是我的实现,它使用一个对象来跟踪我们执行函数的次数、允许执行的最大次数以及 multiply 的最新结果

 'use strict'
//use a counter object to keep track of counts, max number allowed to run and latest result rendered
let counter = {
    count:0,
    max: 0,
    lastResult: 0
};

let multiply = function(a,b){
    if(this.count<this.max){
        this.count++;
        this.lastResult = a*b;
        return a*b;
    }else{
        return this.lastResult;
    }
}

// bind the multiply function to the counter object
multiply = multiply.bind(counter);

let nTimes=function(num,fn){
    this.max = num;
    return fn;
};

// here the nTimes is only executed ONE time, we will also bind it with the counter object
let runTwice = nTimes.call(counter,3,multiply);

console.log(runTwice(1,3)); // 3
console.log(runTwice(2,3)); // 6
console.log(runTwice(3,3)); // 6
console.log(runTwice(4,3)); // 6

请注意,我对简单的multiply 进行了相当多的更改,并将其绑定到counterobject 以使其工作。还使用调用nTimes 绑定counter 对象。

如何使用包装函数实现相同的结果,但对简单的multiply 函数的更改较少?

假设multiply函数很简单:

let multiply = function(a,b){ return a*b };

【问题讨论】:

    标签: javascript wrapper execute


    【解决方案1】:

    您可以对计数和最后一个值使用闭包并检查计数和减量并存储最后一个结果。

    const
        multiply = (a, b) => a * b,
        maxCall = (fn, max, last) => (...args) => max && max-- ? last = fn(...args) : last,
        mult3times = maxCall(multiply, 3);
    
    console.log(mult3times(2, 3));
    console.log(mult3times(3, 4));
    console.log(mult3times(4, 5));
    console.log(mult3times(5, 6));
    console.log(mult3times(6, 7));

    【讨论】:

    • 代码有效,但我很难理解 last = max &amp;&amp; max-- 在做什么??
    • 这是检查conditional (ternary) operator ?: 的一部分,其中检查最大值,如果不为零,则减少max 并分配函数调用的结果。如果max 为零,则分配并返回last
    【解决方案2】:

    看到 Nina 和 Jeto 如何回答您的问题,这里有一个简单且类似的方法,它还保留所有结果的历史记录,以防您以后想获得它们。

    function multiply(a, b) {
      return a * b;
    }
    
    function runMaxNTimes(num, callBack) {
      var results = new Array(num);
      var callTimes = 0;
      return function(...params) {
        return results.length > callTimes ?
          results[callTimes++] = callBack(...params) :
          results[callTimes - 1];
      };
    }
    
    var runTwice = runMaxNTimes(2, multiply);
    
    console.log(runTwice(1, 3)); // 3
    console.log(runTwice(2, 3)); // 6
    console.log(runTwice(3, 3)); // 6
    console.log(runTwice(4, 3)); // 6

    【讨论】:

      【解决方案3】:

      妮娜的回答很棒。这是另一种选择,代码看起来更容易阅读:

      function multiply(a, b) {
        return a * b;
      }
      
      function executeMaxTimes(max, fn) {
        let counter = 0, lastResult;
        return (...args) => counter++ < max 
          ? lastResult = fn(...args) 
          : lastResult;
      }
      
      const multiplyMaxTwice = executeMaxTimes(2, multiply);
      
      console.log(multiplyMaxTwice(1, 3)); // 3
      console.log(multiplyMaxTwice(2, 3)); // 6
      console.log(multiplyMaxTwice(3, 3)); // 6
      console.log(multiplyMaxTwice(4, 3)); // 6

      【讨论】:

      • 谢谢!我试图理解这一点。所以当我们赋值给multiplyMaxTwice 时,executeMaxTimes 会被执行,只执行一次。然后,当我们每次调用multiplyMaxTwice 时,将调用返回的函数,这使得每次调用时计数器都会增加。这是逻辑吗?
      • @MingHuang 实际上,请检查我上次的编辑以获得更清晰的版本(counter 定义为普通变量)。基本上,executeMaxTimes 返回一个将countermax 进行比较的函数,并返回fn 的结果或最后注册的结果(lastResult)。因此,每次调用 multiplyMaxTwice 时,返回的函数都会使用增加的计数器检查该条件。第一次counter 是 0(即 max)所以它返回fn(这里是multiply)的结果,然后是 1(相同),然后是不是 max 所以lastResult返回,后续调用也一样。
      • 在三元语句或 if 语句中更改值是非常酷的技巧。我以前从未像这样使用它。还有一个问题,您的代码中的lastResult 似乎从未声明过,但您可以为其赋值。那里发生了什么?
      • @Jeto 你永远不会声明lastResult 这将失败严格模式
      • @MingHuang 你说得对(nick zoum 也是),我居然忘记声明了,抱歉!刚刚编辑了答案。
      猜你喜欢
      • 2012-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多