【问题标题】:Javascript - Execute an array of functions against a single argumentJavascript - 针对单个参数执行一组函数
【发布时间】:2018-06-06 09:25:12
【问题描述】:

我有一个有两个功能的类。 Add,将函数添加到数组,以及 Execute,根据其参数执行函数数组。我的代码是:

class LazyEvaluation {
  constructor(){
    this.functionQueue = []
  }

  add(fn){
    this.functionQueue.push(fn)
    return this
  }

  evaluate(target){
    for (let i = 0; i < this.functionQueue.length; i++){
      let newArray = target.map(this.functionQueue[i])
      return newArray
    }
  }
}

就目前而言,当我在数组中只有一个函数时,此代码有效。我的问题是只要数组中有多个函数,execute 函数就会为每个函数创建一个新数组。

例如,当functionQueue数组有以下两个函数时:

(function timesTwo(a){ return a * 2 })
(function addOne(a) { return a + 1 })

并且给定执行函数[1, 2, 3]

我需要的输出是[3, 5, 7],但是我得到了[2, 4, 6][2, 3, 4] 的两个独立输出

如何确保执行函数不会为functionQueue中的每个函数创建一个新数组?

【问题讨论】:

    标签: javascript arrays


    【解决方案1】:

    您在for 循环中返回得太早了。您实际上必须 reduce 您的函数传递来自 target 的值:

    class LazyEvaluation {
      constructor(){
        this.functionQueue = []
      }
    
      add(fn){
        this.functionQueue.push(fn)
        return this
      }
    
      evaluate(target){
        return target.map(x => 
          this.functionQueue.reduce((y, f) => f(y), x)
        );
      }
    }
    
    const sums = new LazyEvaluation();
    sums.add(x => x * 2);
    sums.add(x => x + 1);
    
    console.log(
      sums.evaluate([1,2,3])
    );

    【讨论】:

    • 这不会产生所需的输出。
    • @T.J.Crowder 啊,那里读得太快了,我在代码中看到的第一个“错误”就跳了。现在修好了!感谢您的提醒
    • 这仍然不是 OP 说他们想要的输出。
    • 因为我选择了不同的示例数据...这不是要重现确切的示例结果,而是要弄清楚逻辑,对吗?我希望 OP 阅读我的代码 sn-p 并查看它是否符合要求,而不是检查 console.log 的结果。你同意这是一种有效的方法吗?
    • 谢谢,这成功了! - 只是为了理解,是否有可能解释为什么会这样?那么,目标映射的结果会传递给reduce?
    【解决方案2】:

    例如,当functionQueue数组有以下两个函数时:

    (function timesTwo(a){ return a * 2 })
    (function addOne(a) { return a + 1 })
    

    execute函数被赋予[1, 2, 3]

    我需要的输出是 [3, 5, 7] 但是我得到两个单独的输出 [2, 4, 6][2, 3, 4]

    您需要将第一个函数的结果输入到第二个函数中,等等:

    evaluate(target){
      return target.map(value => {
          for (const f of this.functionQueue) {
              value = f(value);
          }
          return value;
      });
    }
    

    现场示例:

    class LazyEvaluation {
      constructor(){
        this.functionQueue = []
      }
    
      add(fn){
        this.functionQueue.push(fn)
        return this
      }
    
      evaluate(target){
        return target.map(value => {
            for (const f of this.functionQueue) {
                value = f(value);
            }
            return value;
        });
      }
    }
    
    const l = new LazyEvaluation();
    l.add(function timesTwo(a){ return a * 2 });
    l.add(function addOne(a) { return a + 1 });
    console.log(l.evaluate([1, 2, 3]));

    【讨论】:

    • const f of this.functionQueue 有效吗? const 不应该是一个永远不会被再次赋值的变量吗?
    • @Michael - 是的,它是有效的——你注意到可运行的例子了吗? :-) 在循环中声明的constlet“变量”的语义与循环中var 变量的行为不同:每次循环迭代都会创建一个不同 变量/常量. for-offor-in 从不尝试修改该变量的值,因此您可以使用常量。 for 确实修改了它,所以在这种情况下你必须使用 let (即使每次都是不同的变量)。
    • @Michael - 新行为对于解决常见的closures in loops problem 非常有用。
    • 我注意到了可运行的示例,甚至在我的 chrome 控制台中运行它以确保 :) 我知道 let f of this.functionQueueconst j... 对我来说听起来不合逻辑。
    • @Michael - :-) 如果你挖掘得足够深,这是合乎逻辑的,每次它实际上都是一个不同的变量/常数。 for-of 是获取迭代器的语法糖,调用其next 方法获取结果对象,然后将变量/常量分配给结果的value 属性;然后重复next 下次调用。这是一个冗长的例子:jsfiddle.net/x098rj7L
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多