【问题标题】:Dynamically build a function动态构建函数
【发布时间】:2019-12-07 20:28:36
【问题描述】:

是否可以根据其他函数参数动态构建函数?

例如:

基础函数:

const someFunction = (functionName, functionParams) => {
  // Function Built here
};

someFunction("colorFunction", ["red", true]);

我希望它构建类似这样的东西: 我需要将 Array 解构为单独的参数,但我不确定这有多简单?而且我不知道如何使用第一个字符串来调用函数名?

functionName(...functionParams);

在我的脑海中会这样工作:

const colorFunction = (color, bool) => {
  console.log("Colour: " + color);
  console.log("Bool: " + bool);
};

对此有点困惑 - 我觉得我不是一百万英里之外,但我不确定!任何帮助都会很棒,谢谢!

编辑 - 为什么?

我有一个带有触发 redux 操作的点击事件的反应组件。理想情况下,这个动作会触发一些东西到我的减速器,并异步调用这个“动态”函数。我可以使用大量 if/else 来做到这一点,但我认为这不是实现这一目标的一种非常干净的方式,如果可以以这种方式构建函数的话。

【问题讨论】:

  • 您为什么想要这样做?做colorFunction(["red", true])不是更容易吗?如果出现问题,您的自定义“函数”的语法(我将函数这个词放在引号中,因为这实际上只是一个美化的函数包装器,它不做任何事情)如果出现问题,那么在代码中的跟踪总是会更长,更烦人,而不仅仅是使用函数直接
  • 先说明你要解决的问题,以便其他人能更好地理解上下文
  • @GrumpyCrouton 我有一个带有点击事件的反应组件,该事件触发一个 redux 操作。理想情况下,这个动作会触发一些东西到我的减速器,并异步调用这个“动态”函数。我可以用大量的 if/else 来做到这一点,但我认为这不是实现这一目标的一种非常干净的方式,如果可以以这种方式构建函数的话。
  • 请阅读The XY Problem

标签: javascript ecmascript-6


【解决方案1】:

首先,您需要确定要动态调用的函数的存储位置。如果它们是全局函数,那么您可以使用 window 调用它们:

const someFunction = (functionName, functionParams) => {
    window[functionName]();
};

如果它们是对象的方法,那么您可以使用该对象做类似的事情:

const someFunction = (functionName, functionParams) => {
    myObject[functionName]();
};

至于如何传递参数,这里有几个选项。如果您正在运行最新版本的 JS,或者使用 polyfill,那么您确实可以使用扩展运算符:

const someFunction = (functionName, functionParams) => {
    window[functionName](...functionParams);
};

否则,您始终可以依赖apply 方法:

const someFunction = (functionName, functionParams) => {
    window[functionName].apply(null, functionParams);
};

apply 方法中的第一个参数是您希望传递给函数的上下文,在您的情况下它似乎没有必要,因此是 null 值。

编辑:如 Bergi 所述,将 bind 更正为 apply

【讨论】:

  • 我很确定您指的是apply,而不是bind。是的,它们绝对应该成为一些局部对象的属性——应该避免使用全局函数。
【解决方案2】:

您正在寻找的是 Function#bind 以创建 thunk - 基本上是一个不带参数的函数,它用于延迟计算。

使用.bind,您可以对函数执行partial application。在您的情况下,您只需应用所有参数,然后只将执行步骤留在最后:

//your function
const colorFunction = (color, bool) => {
  console.log("Colour: " + color);
  console.log("Bool: " + bool);
};

//partially apply all argument to it

const thunk = colorFunction.bind(null, "red", true);

//this can now be passed around and executed at a later point
setTimeout(thunk, 3000);

console.log("wait 3 seconds");

由于 JavaScript 中的函数是 first class members,因此您可以通过这种方式传递任何函数。如果你真的需要一个将其他人变成 thunk 的函数,那么你可以很容易地做到这一点:

const toThunk = (func, args) => func.bind(null, ...args);

您的 someFunction 是哪个,但为了更清楚起见,只是重新命名了名称和参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 2021-11-29
    • 2017-02-24
    • 2021-11-13
    相关资源
    最近更新 更多