包装函数只允许函数 运行 n 次

Only allowing a function to run n times with wrapper function

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

在我的例子中,为简单起见,我只允许它 运行 2 次 num=2 如果我们第一次 运行 runTwice 函数,第二次它将 return multiply 函数使用 multiply 的输入计算的结果。第二次之后的任何调用都不会 运行 multiply 函数,但会 return 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 做了相当多的改动,并将其绑定到 counter 对象以使其工作。还使用对 nTimes 的调用来绑定 counter 对象。

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

假设 multiply 函数非常简单:

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

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

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));

看看 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

Nina 的回答很棒。这是一个替代方案,其代码可能看起来更容易阅读:

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