javascript - 从 JavaScript 函数中提取嵌套函数名称

标签 javascript regex parsing function

给定一个函数,我试图找出其中嵌套函数的名称(只有一层深)。

在我开始使用带有注释的函数之前,一个针对 toString() 的简单正则表达式一直有效。事实证明,一些浏览器存储部分原始源代码,而其他浏览器则根据编译后的内容重建源代码; toString() 的输出可能包含某些浏览器中的原始代码注释。顺便说一句,这是我的发现:

测试对象

function/*post-keyword*/fn/*post-name*/()/*post-parens*/{
    /*inside*/
}

document.write(fn.toString());

结果

Browser      post-keyword  post-name  post-parens  inside
-----------  ------------  ---------  -----------  --------
 Firefox      No            No         No           No
 Safari       No            No         No           No
 Chrome       No            No         Yes          Yes
 IE           Yes           Yes        Yes          Yes
 Opera        Yes           Yes        Yes          Yes

I'm looking for a cross-browser way of extracting the nested function names from a given function. The solution should be able to extract "fn1" and "fn2" out of the following function:

function someFn() {
    /**
     * Some comment
     */
     function fn1() {
         alert("/*This is not a comment, it's a string literal*/");
     }

     function // keyword
     fn2 // name
     (x, y) // arguments
     {
         /*
         body
         */
     }

     var f = function () { // anonymous, ignore
     };
}

解决方案不必是纯正则表达式。

更新:您可以假设我们总是处理有效、正确嵌套的代码,所有字符串文字、注释和 block 都正确终止。这是因为我正在解析一个已被编译为有效函数的函数。

更新 2:如果您想知道这背后的动机:我正在开发一个名为 jsUnity 的新 JavaScript 单元测试框架。 .您可以使用几种不同的格式编写测试和测试套件。其中之一是函数:

function myTests() {
    function setUp() {
    }

    function tearDown() {
    }

    function testSomething() {
    }

    function testSomethingElse() {
    }
}

由于函数隐藏在闭包中,我无法从函数外部调用它们。因此,我将外部函数转换为字符串,提取函数名称,在底部附加“现在运行给定的内部函数”语句,并使用新的 Function() 将其重新编译为函数。如果测试函数中有注释,提取函数名称和避免误报会变得很棘手。因此,我正在寻求 SO 社区的帮助...

更新 3: 我想出了 a new solution这不需要对代码进行大量语义调整。我使用原始源本身来探测一级函数。

最佳答案

外观更改和错误修复

正则表达式必须读作\bfunction\b以避免误报!

如果 nested 的计算结果不为 true,则 block 中定义的函数(例如在循环体中)将被忽略。

function tokenize(code) {
    var code = code.split(/\\./).join(''),
        regex = /\bfunction\b|\(|\)|\{|\}|\/\*|\*\/|\/\/|"|'|\n|\s+/mg,
        tokens = [],
        pos = 0;

    for(var matches; matches = regex.exec(code); pos = regex.lastIndex) {
        var match = matches[0],
            matchStart = regex.lastIndex - match.length;

        if(pos < matchStart)
            tokens.push(code.substring(pos, matchStart));

        tokens.push(match);
    }

    if(pos < code.length)
        tokens.push(code.substring(pos));

    return tokens;
}

var separators = {
    '/*' : '*/',
    '//' : '\n',
    '"' : '"',
    '\'' : '\''
};

function extractInnerFunctionNames(func, nested) {
    var names = [],
        tokens = tokenize(func.toString()),
        level = 0;

    for(var i = 0; i < tokens.length; ++i) {
        var token = tokens[i];

        switch(token) {
            case '{':
            ++level;
            break;

            case '}':
            --level;
            break;

            case '/*':
            case '//':
            case '"':
            case '\'':
            var sep = separators[token];
            while(++i < tokens.length && tokens[i] !== sep);
            break;

            case 'function':
            if(level === 1 || (nested && level)) {
                while(++i < tokens.length) {
                    token = tokens[i];

                    if(token === '(')
                        break;

                    if(/^\s+$/.test(token))
                        continue;

                    if(token === '/*' || token === '//') {
                        var sep = separators[token];
                        while(++i < tokens.length && tokens[i] !== sep);
                        continue;
                    }

                    names.push(token);
                    break;
                }
            }
            break;
        }
    }

    return names;
}

关于javascript - 从 JavaScript 函数中提取嵌套函数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/517411/

相关文章:

javascript - $.post() 回调方法建议

javascript - ASP.NET AJAX 部分回发、动态 JavaScript 值

javascript - 下载图像并将其转换为 QML 中的数据 URI

正则表达式 HTTP header 解析

javascript - 三星智能电视唯一设备标识符

java - java中的正则表达式,搜索特定的字符串模式?

Javascript - 搜索和替换特定单词

Javascript 处理文本区域

vba - XHTML 网站抓取指南

javascript - 如何从请求字符串的参数值中提取相对 URL?