javascript get function body

后端 未结 8 1646
一整个雨季
一整个雨季 2020-12-01 05:44

I have a function e.g.

var test = function () {alert(1);}

How can I get the body of this function?

I assume that the only way is to

相关标签:
8条回答
  • 2020-12-01 05:51

    Simplest Use-Case

    If you just want to execute the body of the function (e.g. with eval or using the Worker API), you can simply add some code to circumvent all the pitfalls of extracting the body of the function (which, as mentioned by others, is a bad idea in general):

    '(' + myFunction + ')()';
    

    I am using this trick in this Worker-related JSFiddle.

    Complete Function Serialization With Accurate Stacktrace

    I also wrote a more complete library that can:

    1. Serialize any kind of function to string
    2. Be able to send that string representation anywhere else, execute it with any custom arguments, and be able to reproduce the original stacktrace

    Check out my CodeBuilder code here.

    Note that much of the code takes care of making sure that we get an accurate stacktrace, wherever we execute the serialized function at a later point in time.

    This fiddle demonstrates a simplified version of that logic:

    1. Use JSON.stringify to properly serialize the function (that comes in handy when, e.g., we want to make it part of a bigger serialization "data package").
    2. We then wrap it in one eval to un-escape the "JSON-ish"-escaped string (JSON does not allow functions + code, so we must use eval), and then in another eval to get back the object we wanted.
    3. We also use //# sourceMappingURL (or the old version //@ sourceMappingURL) to show the right function name in the stacktrace.
    4. You will find that the Stacktrace looks Ok, but it does not give you the correct row and column information relative to the file that we defined the serialized functions in, which is why my Codebuilder makes use of stacktracejs to fix that.

    I use the CodeBuilder stuff in my (now slightly dated) RPC library where you can find some examples of how it is used:

    1. serializeInlineFunction example
    2. serializeFunction example
    3. buildFunctionCall example
    0 讨论(0)
  • 2020-12-01 05:53

    extending @polygenelubricants' answer:

    using: .toString()

    Testee:

    var y = /* olo{lo} */
        /* {alala} */function/* {ff} */ x/*{s}ls{
    }ls*/(/*{*{*/)/* {ha-ha-ha} */
    /*
    
    it's a function
    
    */
    {
      return 'x';
    // }
    }
    /*
    */
    

    By indexOf and lastIndexOf:

    function getFunctionBody(fn) {
        function removeCommentsFromSource(str) {
            return str.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '$1');
        }
        var s = removeCommentsFromSource( fn.toString() );
        return s.substring(s.indexOf('{')+1, s.lastIndexOf('}'));
    };
    
    getFunctionBody(y);
    /*
    "
      return 'x' 
    "
    */
    

    used: rm comments from js source

    0 讨论(0)
  • 2020-12-01 05:55

    This code provides the body when using ES6 arrow functions like var testFn=(q)=>q+1;

    function getFunctionBody(test){  
        var entire = test.toString(); // note: not safe-guarded; this part may fail like this!
        return entire.substring((entire.indexOf("{")+1)||(entire.indexOf("=>")+2),  entire.lastIndexOf("}")!==-1?entire.lastIndexOf("}"):entire.length);
    }
    
    //testing/showcase code
    var tests = [
        function () {alert(1);},
        ()=>{return 1;},
        q=>q+1
    ];
    
    for (var i=0;i<tests.length;i++){
        console.log(tests[i],getFunctionBody(tests[i]));
    }
    

    I originally submitted this code as an edit to polygenelubricants accepted answer, but it was rejected as the changes were considered to be too drastic.

    0 讨论(0)
  • 2020-12-01 06:01

    2015 update

    Upon revisiting the state of function decompilation, it can said that it's generally safe in certain well-considered use cases and enviroments (e.g: Node.js workers with user defined functions).

    It should be put in the same bucket as eval, which is a powerful tool that has its place, but should only be used on rare occasions. Think twice, that's my only advice.

    The conclusions from Kangax's new research:

    • It's still not standard
    • User-defined functions are generally looking sane
    • There are oddball engines (especially when it comes to source code placement, whitespaces, comments, dead code)
    • There might be future oddball engines (particularly mobile or unusual devices with conservative memory/power consumption)
    • Bound functions don't show their original source (but do preserve identifier... sometimes)
    • You could run into non-standard extensions (like Mozilla's expression closures)
    • ES6 is coming, and functions can now look very different than they used to
    • Minifiers/preprocessors are not your friend

    "function decompilation" — a process of getting string representation of a Function object.

    Function decompilation is generally recommended against, as it is a non-standard part of the language, and as a result, leads to code being non-interoperable and potentially error-prone.

    @kangax on comp.lang.javascript

    0 讨论(0)
  • 2020-12-01 06:07

    you can try this functiion:

    function extractFunctionBody(fn) {
        var reg = /function \((.*)\)[ ]?{(.*)}$/g;
        var match = reg.exec(fn.toString().replace(/\n/g, ";"));
        if (match){
            return match[2];
        } else {
            return "";
        }
    }
    
    0 讨论(0)
  • 2020-12-01 06:09

    Try this:

    /\{(\s*?.*?)*?\}/g.exec(test.toString())[0]
    

    test.toString() will hold your entire declaration.

    /{(\s*?.?)?}/g will match everything between your braces

    0 讨论(0)
提交回复
热议问题