【问题标题】:Using object to choose which function to run (dynamically)使用对象选择运行哪个函数(动态)
【发布时间】:2020-02-24 13:20:42
【问题描述】:

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

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 并期望它返回具有提到的 id 的文件夹时,它会迭代对象中的所有文件夹。

因此,为了救援,值用引号和 eval 包裹起来。

这里应该做什么?

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

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

它按预期工作。但是当一个参数应该被传递时,它会说没有定义形式。

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 我在没有 eval 的情况下完成了第一个。

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

【问题讨论】:

  • 为什么let ivar i 在同一个表达式中?选择一个不同的变量名。
  • 对不起。这不是 var i。它是 var ${i} 。这样,aFolder、bFolder 等就被声明为 not i。第二个也没有太大问题,因为这个功能不经常使用。但是第一个函数对于从 eval 中拯救出来很重要,因为这是每次调用的主要函数......
  • 您能否完整地展示您当前的脚本,包括func1func2
  • @TheMaster 我已经解决了那个问题。只是需要第二个帮助。谢谢。
  • 在不同的帖子中提出不同的问题。混合问题是不受欢迎的。

标签: javascript google-apps-script eval


【解决方案1】:

好吧,你不应该使用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 示例

【讨论】:

  • 谢谢。你的回答给了我标题,我想避免 eval 进行函数调用。我只需要找出第二个问题,但它必须是相似的。
  • 请详细说明您要实现的目标以及当前的问题是什么。我会尽力提供帮助
  • 谢谢。这有点解决了。您可以在下面查看我的代码。我只是想确保使用 'this' 没有像 eval 这样的副作用。
【解决方案2】:

感谢 stackoverflow 和人们的贡献,我得以轻松解决我的问题。 我的两个问题都是动态调用一个函数,而第一个更容易作为@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();
}

第二个也类似,但这次分配变量也是动态的。在来自的评论的帮助下,这也得到了解决 https://stackoverflow.com/a/28063322/12775761

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

->

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

如果“this”没有邪恶,我会这样使用。 (这是服务器端功能,所以我不能使用窗口)

【讨论】:

  • Witt 到底需要这么多变量吗?为什么var ${i}?你的方法有问题。
  • @TheMaster 因为var的名字和函数是在运行的时候动态选择的。
  • 为什么你不能用switch...case在同一个函数中做所有事情?
  • @TheMaster switch-case 有同样的问题,即迭代所有值,不仅是被调用的值,即使有中断,我也删除了该代码。而且我更喜欢对象方法而不是 switch-case 当它有超过 5 个要通过时。至少在这种情况下,它更容易处理并且行动更快。而且我不明白为什么当每个功能都有不同的用途时,您为什么要使用一个功能。如果将所有函数都声明为一个,那么没有人会理解代码。
  • 您能在..move files to the destination above. 中显示其余代码吗?我很难想象你想要做什么。
猜你喜欢
  • 1970-01-01
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 2014-12-29
  • 2013-01-22
  • 2011-01-09
相关资源
最近更新 更多