使用对象来选择要 运行 的函数(动态地)

Using object to choose which function to run (dynamically)

从客户端 (html) 发送表单,服务器端通过 select 选项之一决定 运行 哪个函数。

const decideWho = (form) => {
  const choice = form.choice;
  const obj = { key1 : 'func1(form.input1)',
key2 : 'func2(form.input2)'......};
return eval(obj[choice]||obj[default]);
}

由于其他一些问题,此代码被放置并且 Josh Wulf 提到了使用 eval 的危险。

我来了。我无法搜索与我的情况相关的内容,所以如果您知道任何已回答的问题,请告诉我。

我的问题是,一开始我只是把 obj 的值不带引号。然后灾难发生了。当调用最后一行 obj[choice]||obj[default] 时,会调用 obj 中的所有函数,并且某些函数会重复迭代。我不知道出了什么问题。

不仅如此

const someFunc = () => {
const a = {
      sourceFolder: "",
      aFolder: "1OoK3j",
      bFolder: "1M_cyv",
      cFolder: "11maBJ",
      dFolder: "1QxA8P",
      eFolder: "11lG"};
    for (let i in a) 
      eval(`var ${i} = getFolder(a['${i}']);`);

..move files to the destination above.
}


const getFolder = id => {
  try {
    if (id) {
      return DriveApp.getFolderById(id);
    } else return DriveApp.getRootFolder();
  } catch (e) {
  // If the folder by the id doesn't exists, return root folder.
    return DriveApp.getRootFolder();
  }
}

我不想使用相同的函数声明每个文件夹。所以我把它们放在 obj 中,没有 eval,迭代。

for (let i in a) var i = getFolder(a[i]);

又是灾难。当我调用 aFolder 期望它 return 提到的 id 的文件夹时,它迭代对象中的所有文件夹。

因此,为了救援,值用引号括起来并暂时求值。

这里应该做什么?

** 已编辑 ** 我正在尝试采用函数构造函数。

const aa = form => `id: ${form.id}`;
const bb = () => "I'm b";
const aaa = form => {
  const obj = {
    key1 : 'aa(form)',
    key2 : 'bb'
  };
  const handleIt = new Function('return ' + obj[form.choice])();
  console.log(handleIt());
}
const cc = () => {
  let form = {id: 'student 1', choice: 'key1'};
  aaa(form);
  form = {id: 'student 2', choice: 'key2'};
  aaa(form); 
}

这些简化只是为了问一个问题,但真正的功能很长。 当我表演

form = {id: 'student 2', choice: 'key2'};
  aaa(form); 

它按预期工作。但是当应该传递一个参数时,它说 form is not defined.

let form = {id: 'student 1', choice: 'key1'};
  aaa(form);

如果函数构造函数是解决方案,我需要在哪里以及如何添加参数?

const aaa = form => {
  const obj = {
    key1 : 'aa(form)',
    key2 : 'bb'
  };
  const handleIt = new Function('return ' + obj[form.choice])();
  console.log(handleIt());
}

已编辑 2 我在没有评估的情况下完成了第一个。

const decideWho = myForm => {
  const obj = {
    key1 : func1(myForm),
    key2 : func2()
  };
  const handleIt = () => {return obj[myForm.choice];};
  console.log(handleIt());
}

嗯,您不应该使用 eval 并不意味着您不能使用 new Function。事实上,这个 question 对两者之间的区别进行了很好的讨论

所以..也许你应该把你的代码从

const decideWho = (form) => {
  const choice = form.choice;
  const obj = { 
     key1 : 'func1(form.input1)',
     key2 : 'func2(form.input2)'
  };
  return eval(obj[choice]||obj[default]);
}

类似于:

const decideWho = (form) => {
  const choice = form.choice;
  const obj = { 
     key1 : 'return true',
     key2 : 'return 7'
  };
  return new Function(obj[choice]||obj[default]);
}

然后只需致电您的处理程序:

 const funcHandler = decideWho(myForm)
 funcHandler()

如果你也想传递参数,请参考这个MDN示例

感谢 Whosebug 和人们的贡献,我得以轻松解决我的问题。 我的两个问题都是动态调用函数,第一个问题根据@ymz 的建议更容易。

const decideWho = (form) => {
  const choice = form.choice;
  const obj = { key1 : 'func1(form.input1)',
key2 : 'func2(form.input2)'......};
return eval(obj[choice]||obj[default]);
}

改为

const decideWho = myForm => {
  const obj = {
    key1 : ()=> func1(myForm),
    key2 : ()=> func2()
  };
  const handleIt = () => obj[`${myForm.choice}`]();
  return handleIt();
}

第二个也类似,但这次赋值变量也是动态的。在评论的帮助下也解决了这个问题

for (let i in a) 
  eval(`var ${i} = getFolder(a['${i}']);`);

->

for (let i in a) this[`${i}`] = getFolder(a[i]);

如果"this"没有邪气,我就这样用。 (这是服务器端功能,所以我不能使用 window)