11

可能重复:
如何从 javascript 动态获取函数参数名称/值

我目前正在使用 javascript (node.js) 开发一个项目,该项目让我试图从函数中获取参数名称数组(不是值,我不需要参数)。我目前正在使用 Function.toString() 来获取函数字符串,然后针对该字符串运行正则表达式以获取我的参数列表。

让我们看一个简单的例子:

var myFunction = function (paramOne, paramTwo) { ... }

对此运行我的正则表达式,然后做一些字符串魔术(拆分等),我希望得到一个像这样的数组:

paramList = ['paramOne', 'paramTwo']

我有一些可行的方法,但我觉得它可能不是最好的解决方案,因为 javascript 允许您将一些时髦的字符用于变量名,并且 javascript 将允许您在多行上定义函数。

这是我目前拥有的:

function.*[\w\s$]*(\((.*[\w\s,$]*)\))

这给了我第 1 组中的“匹配”,然后是第 2 组中没有括号的参数列表,这很酷。这真的是做我想做的最好的方法吗?我可以为此使用更好的正则表达式吗?我并不是真的在寻找“更简单”的东西,而实际上只是在寻找可以捕捉所有可能情况的东西。

任何帮助将不胜感激,并提前非常感谢!

4

3 回答 3

23

前言:到目前为止,处理这个问题的最好方法是使用 JavaScript 解析器,而不是尝试使用单个正则表达式。正则表达式可以是解析器的一部分,但没有一个正则表达式可以完成解析器的工作。JavaScript 的语法(就像大多数编程语言一样)过于复杂且对上下文敏感,无法用一两个简单的正则表达式来处理。有几个用 JavaScript 编写的开源 JavaScript 解析器。我强烈建议使用其中之一,而不是下面的内容。


最简单的方法是捕获第一组括号中的所有内容,然后用于split(/\s*,\s*/)获取数组。

例如:

var str = "function(   one  ,\ntwo,three   ,   four   ) { laksjdfl akjsdflkasjdfl }";
var args = /\(\s*([^)]+?)\s*\)/.exec(str);
if (args[1]) {
  args = args[1].split(/\s*,\s*/);
}
console.log("args: ", args);

以上是如何工作的:

  1. 我们使用/\( *([^)]+?) *\)/匹配第一个左括号(\(因为(在正则表达式中是特殊的),然后是任意数量的可选空格,然后是捕获组,捕获除右括号之外的所有内容(但非贪婪),然后是任意数量的可选空格,其次是收盘)

  2. 如果我们成功了,我们使用 拆分/\s*,\s*/,这意味着我们拆分的序列是零个或多个空白字符 ( \s*),后跟一个逗号,后跟零个或多个空白字符(这个空白就是为什么我的示例函数中的 args 如此奇怪) .

从示例中可以看出,它处理前导空格(在(第一个参数之后和之前)、逗号周围的空格和尾随空格——包括换行符。它不会尝试处理参数列表中的注释,这会使事情变得非常复杂。

注意:上面不处理 ES2015 的默认参数值,它可以是任意的表达式,包括一个包含) - 的表达式,它通过提前停止搜索来破坏上面的正则表达式:

var str = "function(   one  ,\ntwo = getDefaultForTwo(),three   ,   four   ) { laksjdfl akjsdflkasjdfl }";
var args = /\(\s*([^)]+?)\s*\)/.exec(str);
if (args[1]) {
  args = args[1].split(/\s*,\s*/);
}
console.log("args: ", args);

这给我们带来了完整的循环:使用 JavaScript 解析器。:-)

于 2012-12-19T12:53:17.377 回答
4

执行以下操作:

var ar = str.match(/\((.*?)\)/);
if (ar) {
  var result = ar[0].split(",");
}

记住 ?在 * 之后做一个非贪婪的发现

于 2012-12-19T13:00:04.173 回答
2

让我建议您使用正则表达式:

  • [match]/function[^(]*\(([^)]*)\)/将匹配参数列表
  • [split] /\W+/(针对第一个匹配数据的结果)将匹配拆分为参数列表

因此,代码应如下所示:

var s = "function moo (paramOne, paramTwo) { alert('hello'); }";
var s2 = s.match(/function[^(]*\(([^)]*)\)/)[1];
var paramList = s2.split(/\W+/);
于 2012-12-19T13:10:44.247 回答