检查一个函数是否存在于 nodejs 中的另一个函数中

Ada*_*yai 0 node.js webpack

提出以下情况:

function functionExists(functionName) {
    if (typeof window[functionName] == 'function') console.log("It's a function");
}
Run Code Online (Sandbox Code Playgroud)

什么是在同等功能nodejsfunctionExists那里是没有全局window变量?

具体情况:

我的具体情况使用了webpack而不是nodejs,但基本上问题是一样的。我可以window在这里使用,但是干净地实现所有内容会太复杂,并且不建议webpack将事情减轻到window全局变量。

基本上,我有一个PHP后端,它生成一个 html <form>,通过一个data属性向它添加一些选项。当页面加载时,我的 javascript 会初始化它<form>并为其提供一系列功能(例如验证)。javascript 对这个表单所做的另一件事是它解析它的数据属性,而不是正常的页面重新加载提交,它改变了表单,以便它通过ajax请求提交给服务器。

当这个提交发生时,它被设置,按钮和整个表单被禁用,直到我的Ajax脚本发回响应。这是如何完成的,是我有一个Project_Form类,当它初始化时,将自身附加到jQuery提交事件,停止基本提交事件,并运行一个内部函数,该函数将 ajax 请求发送到 api 方法。设置了 ajax 请求,当收到响应时,同一个实例化类将收到此响应,因此我可以继续使用它。

当表单收到响应时,它必须对它做一些事情。在最基本的情况下,它必须向用户显示成功消息,但还有一些更复杂的情况,例如,它必须进行页面重定向(例如登录表单)。现在,它被设置为默认情况下,它将显示一条消息,但是当我在 PHP 中定义此表单时,我可以选择“劫持”此默认行为,而不是将 ajax 响应发送到一个自定义函数,它将专门解决这种情况。

当我在 PHP 中渲染表单时,我已经知道表单应该在哪里发送成功响应(到哪个 javascript 函数),但我只能通过字符串将此信息提供给 javascript。所以我的Project_Form班级应该获取这个字符串,并且应该尝试从中获取一个它将使用的函数。这就是我的问题的来源。

jfr*_*d00 5

除非你特别知道这是一个全局函数(在 nodejs 中几乎从来没有这种情况),默认情况下,nodejs 中的函数范围是模块,没有办法像你在window对象中那样通过字符串名称查找它们浏览器,就像无法在 Javascript 中的函数内按名称查找局部变量一样。

通常,不要通过字符串名称传递函数。或者,如果必须,那么您需要创建一个查找表,您可以根据该表检查函数名称。

我建议你在这里解释你试图解决的真正问题,因为通过字符串名称传递函数不是你通常想要做的事情。

有一点使用eval()可以查看字符串是否表示范围内的函数名称:

// Warning, you must know that the argument f (if it is a string) does not
// contain harmful Javascript code because it will be used with eval()
function isFunction(f) {
   // if already a function reference
   if (typeof f === "function") {
       return true;
   // see if string represents a function name somewhere in scope
   } else if (typeof f === "string") {
       try {
           return eval(`typeof ${f} === "function"`);
       } catch(e) {
           return false;
       }
   } else {
       return false;
   }
}
Run Code Online (Sandbox Code Playgroud)

注意:这会测试函数是否在函数的范围内isFunction()。如果要测试它是否在当前范围内,则需要执行以下操作:

eval(`typeof ${f} === "function"`) 
Run Code Online (Sandbox Code Playgroud)

内联在您当前的范围内,以便它在您要从中进行查找的范围内运行。

要考虑使用它,您必须知道字符串的来源是安全的,并且不能包含有害代码。但是,正如我之前所说,最好以不同的方式设计您的程序,这样您就不会通过字符串名称来引用函数。

而且,这是一个可运行的代码片段,显示它的实际运行情况(也适用于 node.js 模块):

// Warning, you must know that the argument f (if it is a string) does not
// contain harmful Javascript code because it will be used with eval()
function isFunction(f) {
   // if already a function reference
   if (typeof f === "function") {
       return true;
   // see if string represents a function name somewhere in scope
   } else if (typeof f === "string") {
       try {
           return eval(`typeof ${f} === "function"`);
       } catch(e) {
           return false;
       }
   } else {
       return false;
   }
}
Run Code Online (Sandbox Code Playgroud)


问题编辑后添加更多

如果您只将函数名称作为字符串,并且它指向的函数不是某个已知对象的属性,那么我所知道的将该字符串转换为函数引用的唯一方法是使用eval().

您可以直接使用eval()例如执行它,eval(functionName + "()")或者您可以获得对该函数的引用eval("let fn = " + functionName),然后使用新定义的fn变量来调用该函数。

如果您控制可以引用的各种函数(因为它们是您的 Javascript),那么您可以使所有这些函数成为您的 Javsacript 中已知对象的属性:

 const functionDispatcher = {
      function1,
      function2,
      function3,
      function4
 }
Run Code Online (Sandbox Code Playgroud)

然后,而不是使用eval(),您可以functionDispatcher像之前引用的那样从对象中引用它们window(除非这不是全局的),如下所示:

functionDispatcher[someFunctionName]();
Run Code Online (Sandbox Code Playgroud)

这将是比 using 更好的选择,eval()因为通过不安全的字符串插入随机代码的风险较小。