从函数定义得到参数列表的正则表达式[复制]

时间:2022-02-06 21:48:40

Possible Duplicate:
How to get function parameter names/values dynamically from javascript

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

I'm currently working on a project in javascript (node.js) that has me trying to get an array of parameter names (NOT values, I do not need arguments) from a function. I'm currently using Function.toString() to get the function string and then running a regex against that to get my parameter list.

我目前正在开发一个javascript项目(node.js),它让我从一个函数中获取一个参数名称数组(不是值,我不需要参数)。我现在使用Function.toString()来获取函数字符串,然后运行regex来获取参数列表。

Let's take the following SIMPLE example:

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

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

Running my regex against this, and then doing some string magic (split, etc) I would expect an array back like this:

运行我的regex,然后执行一些字符串魔术(分割,等等),我希望返回一个这样的数组:

paramList = ['paramOne', 'paramTwo']

I have something that works but I'm feeling like it's probably not the best solution given some of the funky characters javascript lets you use for variable names and that javascript will let you define functions on multiple lines.

我有一些有用的东西,但我觉得它可能不是最好的解决方案,因为javascript允许你对变量名使用一些时髦的字符,javascript允许你在多行中定义函数。

Here is what I currently have:

以下是我目前的情况:

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

This gives me my "match" in group 1 and then my param list without parens in group 2, which is cool. Is this really the best way to do what I want? Is there a better regular expression I could use for this? I'm not really looking for something "simpler" but really just something that could catch all possible situations.

这给了我第一组中的“匹配”,然后是第二组中没有param的列表,这很酷。这真的是做我想做的事情的最好方式吗?有更好的正则表达式可以用于此吗?我并不是在寻找“更简单”的东西,而是真正能抓住所有可能的情况的东西。

Any help would be appreciated, and many thanks in advance!

如有任何帮助,我们将不胜感激,并提前表示感谢!

3 个解决方案

#1


18  

The easiest thing would be to capture everything in the first set of parens, and then use split(/\s*,\s*/) to get the array.

最简单的方法是捕获第一个parens集合中的所有内容,然后使用split(/\s*、\s*/)来获取数组。

E.g.:

例如:

var str = "function(   one  ,\ntwo,three   ,   four   ) { laksjdfl akjsdflkasjdfl }";
var args = /\(\s*([^)]+?)\s*\)/.exec(str);
if (args[1]) {
  args = args[1].split(/\s*,\s*/);
}
snippet.log("args: " + JSON.stringify(args));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

How the above works:

以上是如何工作的:

  1. We use /\( *([^)]+?) *\)/ to match the first opening parenthesis (\( since ( is special in regexes), followed by any amount of optional whitespace, followed by a capture group capturing everything but a closing parenthesis (but non-greedy), followed by any amount of optional whitespace, followed by the closing ).

    我们使用/ \(*((^))+ ?)* \)/匹配第一个开括号(\(因为在regex(特殊),其次是任何数量的可选的空白,紧随其后的是一个捕获组捕捉一切但关闭括号(但非贪婪),其次是任何数量的可选的空白,其次是关闭)。

  2. If we succeed, we split using /\s*,\s*/, which means we split on sequences which are zero or more whitespace characters (\s*) followed by a comma followed by zero or more whitespace characters (this whitespace thing is why the args in my example function are so weird).

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

As you can see from the example, this handles leading whitespace (after the ( and before the first argument), whitespace around the commas, and trailing whitespace — including line breaks. It does not try to handle comments within the argument list, which would markedly complicate things.

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


Side note: Be sure to test on your target browsers, Function#toString returning some form of the source code is a non-standard feature. It's broadly supported (in desktop browsers), but not standard. Note that some browsers will include comments, others will not; if someone includes comments in the function arguments, it could well mess up your parsing of them. You might kick around the Prototype source code for its Function#argumentNames extension, as they've already been down this road...

附加说明:确保在目标浏览器上进行测试,函数#toString返回某种形式的源代码是一个非标准特性。它得到广泛的支持(在桌面浏览器中),但不是标准的。注意,有些浏览器会包含注释,有些则不会;如果有人在函数参数中包含注释,那么很可能会打乱对它们的解析。您可能会对其函数#argumentNames扩展的原型源代码感兴趣,因为它们已经在这条路上了……

#2


3  

Do as following:

做如下:

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

Remember ? after * does a non greedy find

还记得吗?后*做一个非贪婪的发现

#3


2  

Let me suggest you using regular expressions:

我建议你使用正则表达式:

  • [match] /function[^(]*\(([^)]*)\)/ will match the argument list
  • (比赛)/函数\[^]*(((^))*)\)/将匹配参数列表
  • [split] /\W+/ (against the results of the first match data) will split the match into params list
  • [split] /\W+/(针对第一个匹配数据的结果)将把匹配分割为params列表

So, the code should look like this:

代码应该是这样的:

var s = "function moo (paramOne, paramTwo) { alert('hello'); }";
var s2 = s.match(/function[^(]*\(([^)]*)\)/)[1];
var paramList = s2.split(/\W+/);

#1


18  

The easiest thing would be to capture everything in the first set of parens, and then use split(/\s*,\s*/) to get the array.

最简单的方法是捕获第一个parens集合中的所有内容,然后使用split(/\s*、\s*/)来获取数组。

E.g.:

例如:

var str = "function(   one  ,\ntwo,three   ,   four   ) { laksjdfl akjsdflkasjdfl }";
var args = /\(\s*([^)]+?)\s*\)/.exec(str);
if (args[1]) {
  args = args[1].split(/\s*,\s*/);
}
snippet.log("args: " + JSON.stringify(args));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

How the above works:

以上是如何工作的:

  1. We use /\( *([^)]+?) *\)/ to match the first opening parenthesis (\( since ( is special in regexes), followed by any amount of optional whitespace, followed by a capture group capturing everything but a closing parenthesis (but non-greedy), followed by any amount of optional whitespace, followed by the closing ).

    我们使用/ \(*((^))+ ?)* \)/匹配第一个开括号(\(因为在regex(特殊),其次是任何数量的可选的空白,紧随其后的是一个捕获组捕捉一切但关闭括号(但非贪婪),其次是任何数量的可选的空白,其次是关闭)。

  2. If we succeed, we split using /\s*,\s*/, which means we split on sequences which are zero or more whitespace characters (\s*) followed by a comma followed by zero or more whitespace characters (this whitespace thing is why the args in my example function are so weird).

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

As you can see from the example, this handles leading whitespace (after the ( and before the first argument), whitespace around the commas, and trailing whitespace — including line breaks. It does not try to handle comments within the argument list, which would markedly complicate things.

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


Side note: Be sure to test on your target browsers, Function#toString returning some form of the source code is a non-standard feature. It's broadly supported (in desktop browsers), but not standard. Note that some browsers will include comments, others will not; if someone includes comments in the function arguments, it could well mess up your parsing of them. You might kick around the Prototype source code for its Function#argumentNames extension, as they've already been down this road...

附加说明:确保在目标浏览器上进行测试,函数#toString返回某种形式的源代码是一个非标准特性。它得到广泛的支持(在桌面浏览器中),但不是标准的。注意,有些浏览器会包含注释,有些则不会;如果有人在函数参数中包含注释,那么很可能会打乱对它们的解析。您可能会对其函数#argumentNames扩展的原型源代码感兴趣,因为它们已经在这条路上了……

#2


3  

Do as following:

做如下:

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

Remember ? after * does a non greedy find

还记得吗?后*做一个非贪婪的发现

#3


2  

Let me suggest you using regular expressions:

我建议你使用正则表达式:

  • [match] /function[^(]*\(([^)]*)\)/ will match the argument list
  • (比赛)/函数\[^]*(((^))*)\)/将匹配参数列表
  • [split] /\W+/ (against the results of the first match data) will split the match into params list
  • [split] /\W+/(针对第一个匹配数据的结果)将把匹配分割为params列表

So, the code should look like this:

代码应该是这样的:

var s = "function moo (paramOne, paramTwo) { alert('hello'); }";
var s2 = s.match(/function[^(]*\(([^)]*)\)/)[1];
var paramList = s2.split(/\W+/);