[ACCEPTED]-What are some real world uses for function.toString()?-javascript

Accepted answer
Score: 17

Well, you can use it to easily redefine 5 a function:

function x() { alert('asdf'); }
eval(x.toString().replace('asdf','hello'));
x();

This will alert the string "hello" instead 4 of the string "asdf".

This may be useful. On 3 the other hand, self modifying code is often 2 frowned upon because of the difficulty to 1 maintain it...

Score: 13

This is an old question, but here are my 14 2 cents.

Using node.js, this becomes useful 13 for creating functions on the serverside 12 which are then embedded into a page and 11 sent to the client.

For example, the dot.js 10 template engine works by first compiling 9 templates into a function, which can then 8 be executed to generate the HTML code.

eg:

var compiled = dot.compile("<h1>{{=it.header}}</h1>");
var html_output = compiled({header: "hello world"});

So, if 7 we want to make use of templates in the 6 client without each client having to compile 5 them first, we can serve them a page containing 4 the evaluated result of:

"var compiled = " + dot.compile("<h1>{{=it.header}}</h1>").toString();

which will then 3 provide a "compiled" function client-side, for 2 use compiling data such as that sent from 1 ajax requests into HTML client-side.

Score: 10

I've used it to automatically generate named-parameter 7 versions of functions. For example, if you 6 have a function

function f(a, b, c) {
    return a * b + c;
}

you can extract the parameter 5 names from f.toString() and use it to generate a function 4 that you can call like this:

namedParametersF({ a: 2, b: 3, c: 4}); // f(2, 3, 4);

Here's an implementation 3 of this idea:

// Get an array of parameter names from a function
Function.parameters = function(f) {
    // Find the parameter list in f.toString()
    var m = /function[^\(]*\(([^\)]*)\)/.exec(f.toString());
    if (!m) {
        throw new TypeError("Invalid function in parameters");
    }

    var params = m[1].split(',');
    for (var i = 0; i < params.length; i++) {
        // trim possible spaces
        params[i] = params[i].replace(/^\s*|\s*$/g, '');
    }
    return params;
};

// Convert f to a function that accepts named parameters
Function.withNamedParameters = function(f) {
    var params = Function.parameters(f);
    return function(args) {
        var argsArray = new Array(params.length);
        for (var i = 0; i < params.length; i++) {
            argsArray[i] = args[params[i]];
        }
        return f.apply(this, argsArray);
    };
};

I have a slightly more flexible 2 implementation of this that can go the other 1 direction (Function.withPositionalParameters) on GitHub: http://gist.github.com/132782.

Score: 7

Elaborating on the idea raised above by James Westgate, here's an example of 5 a use of toString() to create, dispatch & receive 4 a web worker:

/*
 * @param fun the function to carry out in the web worker
 * @param mes the message to send to the web worker
 * @param com the function to do on completion
 * creates, dispatches & receives a web worker
 */
function wor(fun, mes, com) {
   var wor = new Worker(URL.createObjectURL(new Blob([
         'self.onmessage = ' + fun.toString()], {
         type: 'application/javascript'
   })));       
   wor.postMessage(mes);
   wor.onmessage = com;
}

By turning the function into 3 a string we can use it to so create a function 2 in an object URL, which is then parsed & executed 1 on receiving data.

Score: 6

I think this is essentially used for debugging 1 purposes...

Score: 4

Multi-line strings in Javascript source.

As described in this blog post by @tjanczuk, one of the massive inconveniences 11 in Javascript is multi-line strings. But 10 you can leverage .toString() and the syntax for multi-line 9 comments (/* ... */) to produce the same results.

By 8 using the following function:

function uncomment(fn){
  return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
};

…you can then pass in multi-line 7 comments in the following format:

var superString = uncomment(function(){/*
String line 1
String line 2
String line 3
*/});

In the 6 original article, it was noted that Function.toString()'s behaviour 5 is not standardised and therefore implementation-discrete 4 — and the recommended usage was for Node.js 3 (where the V8 interpreter can be relied 2 on); however, a Fiddle I wrote seems to work on every browser I have available to me (Chrome 27, Firefox 21, Opera 1 12, Internet Explorer 8).

Score: 3

One real-world example is in Prototype, which uses 4 this to determine the names of the arguments 3 to methods in subclasses to see if it should 2 do its special superclass handling stuff (which involves the 1 special argument $super).

Score: 3

CouchDb's view definitions take their map and 4 reduce as strings. With function.toString you can write these functions 3 as proper functions (so an IDE/syntax checker 2 can help you), then convert them to strings 1 when inserting them.

Score: 3

Angular JS uses this pattern to inject it's 3 built-in services. All you need to do is 2 use a service name (prefixed by "$") as 1 a parameter to your function - for example: "$http".

See the exact usage on Github.

Score: 2

I believe Visual Studio's Intellisense uses 6 this to locate and parse optional XML Code Comments for any 5 such documented functions, such as below:

function areaFunction(radiusParam)
{
    /// <summary>Determines the area of a cicle based on a radius parameter.</summary>
    /// <param name="radius" type="Number">The radius of the circle.</param>
    /// <returns type="Number">Returns a number that represents the area.</returns>
    var areaVal;
    areaVal = Math.PI * radiusParam * radiusParam;
    return areaVal;
}

Conceivably 4 you could parse this yourself at run-time, for 3 the presenting documentation at will or 2 supplementing the details of an unhandled 1 exception.

Score: 1

In multi-windowed web applications, if you 20 need to share a function between windows 19 to be executed at a later time, but can't 18 guarantee that the owner of that function 17 (the window it was defined in) will be alive 16 at execution time, you can serialize the 15 function using toString(), store it to the pertinent 14 window, and call eval() on it at a later time/time 13 of execution. Granted, using eval() has its own 12 warts, but this seems like a legitimate 11 use case (we need to reinvoke the script 10 parsing engine to turn the serialized function 9 back into executable code).

This is the 8 only sure-fire way to not get access denied 7 errors in this scenario. The gotcha here 6 is that execution context now becomes the 5 window we are calling eval() from, and not the 4 scope that the function was originally defined 3 in, so care must be taken not to rely on 2 variables outside of the function's immediate 1 scope.

Score: 0

Could be used as a way of coding up Web 2 Workers without having to place functions 1 in separate files.

Score: 0

You can utilize function stringification 8 to include a function in a generated page 7 with syntax highlighting of the function 6 in the source. I've done this with CoffeeScript 5 too, with the function written in and highlighted 4 as CoffeeScript, but treated as a JavaScript 3 function since it... is one. Or since it's 2 compiled to one when the rest of the CoffeeScript 1 is compiled.

See this on github:

        error_handling = ->
            d = document.createElement "div"
            d.className = "error bubble script-error"
            window.onerror = (error)->
                document.body.appendChild d
                d.style.position = "absolute"
                d.style.borderRadius = d.style.padding = 
                d.style.bottom = d.style.right = "5px"
                d.innerText = d.textContent = error

        body += """
            <script>~#{error_handling}()</script>
            <style>
                .error {
                    color: red;
                }
                .error.bubble {
                    background: rgba(255, 0, 0, 0.8);
                    color: white;
                }
                body {
                    font-family: Helvetica, sans-serif;
                }
            </style>
        """
Score: 0

assert arg not null

exports.warnNull = function() {
  var func = arguments.callee.caller
  var args = func.toString().match(/function\s*\w*\((.*?)\)\s*/)[1].split(',').map(Function.prototype.call.bind(String.prototype.trim))
  var params = Array.prototype.slice.call(arguments)
  for (var i = 0; i < params.length; i ++) {
    if (!params[i]) {
      console.warn(gutil.colors.yellow('缺少变量 : ' + args[i]))
    }
  }
}

wrap long String

exports.controller = function(){
/*
app.controller('{{ controllerName }}', function({{ injects }}) {
  // ...
})
*/
}.toString().slice(16, -4)

0

Score: 0

toString is a serializer method. In some cases, we 4 need to store function logic to storage 3 such as database or transport via internet. It's 2 also a kind of data to describe 'how to 1 do something'.

More Related questions