【问题标题】:Regular Expression to get parameter list from function definition [duplicate]正则表达式从函数定义中获取参数列表
【发布时间】:2012-12-19 12:51:48
【问题描述】:

可能重复:
How to get function parameter names/values dynamically from javascript

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

让我们举个简单的例子:

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

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

paramList = ['paramOne', 'paramTwo']

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

这是我目前拥有的:

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

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

任何帮助将不胜感激,并在此先感谢!

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    前言: 到目前为止,处理此问题的最佳方法是使用 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. 我们使用/\( *([^)]+?) *\)/ 来匹配第一个左括号(\(,因为( 在正则表达式中是特殊的),然后是任意数量的可选空格,然后是一个捕获组,捕获除右括号之外的所有内容(但非-greedy),后跟任意数量的可选空格,然后是结束 )

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

    从示例中可以看出,它处理前导空格(( 之后和第一个参数之前)、逗号周围的空格和尾随空格 — 包括换行符。它确实尝试处理参数列表中的 cmets,这会使事情明显复杂化。

    注意:上面不处理 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 解析器。 :-)

    【讨论】:

    • 你觉得我应该怎么做?这就是我试图用我的正则表达式做的,但也许有不同的方法?您是否认为我可以只 indexOf "(" 和 ")" 然后拆分两者之间的内容?这会比疯狂的正则表达式更好吗?
    • @JasonL.:我在答案中添加了一些代码(以及一个活生生的例子)。
    • 谢谢!您的解决方案比我想象的要简单得多。我目前正在尝试使用 javascript 允许的所有不同变体。这会捕捉到 javascript 允许的任何疯狂的特殊字符吗(最著名的一个是不赞成的样子)?我还应该注意,这仅适用于 node.js 环境,所以我真的只需要担心 V8 :)
    • @JasonL.: 上面的关键位是 1) 第一个正则表达式 [^)]+ 中捕获组的内容,意思是“一个或多个不是右括号”,以及 2) 拆分 /\s*,\s*/ 中的正则表达式,它拆分零个或多个空白字符后跟逗号,后跟零个或多个空白字符的序列。所以你应该对所有奇怪而美妙的有效标识符都没有问题。您必须担心的是cmets。 :-)
    • 啊,好点子。看起来 V8 确实包含 cmets。我想我应该查看您链接的来源,看看他们如何忽略 cmets :)
    【解决方案2】:

    执行以下操作:

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

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

    【讨论】:

    • /(?<=\().*?(?=\))/ 开始于((?<=\() 内容(?=\)) 结束于)
    【解决方案3】:

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

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

    所以,代码应该是这样的:

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

    【讨论】:

      猜你喜欢
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多