34

Can Javascript get a function as text? I'm thinking like the inverse of eval().

function derp() { a(); b(); c(); }

alert(derp.asString());

The result would be something like "a(); b(); c();"

Does it exist?

Brandon
  • 411
  • 2
  • 5
  • 4
  • It's possible to convert a JavaScript function to text, and it's also possible to [convert the text back into a function](http://stackoverflow.com/questions/2573548/given-a-string-describing-a-javascript-function-convert-it-to-a-javascript-func). – Anderson Green Apr 26 '13 at 22:06

2 Answers2

49

Updated to include caveats in the comments below from CMS, Tim Down, MooGoo:

The closest thing available to what you're after is calling .toString() on a function to get the full function text, like this:

function derp() { a(); b(); c(); }
alert(derp.toString()); //"function derp() { a(); b(); c(); }"

You can give it a try here, some caveats to be aware of though:

  • The .toString() on function is implementation-dependent (Spec here section 15.3.4.2)
    • From the spec: An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation string is implementation-dependent.
    • Noted differences in Opera Mobile, early Safari, neither displaying source like my example above.
  • Firefox returns a compiled function, after optimization, for example:
    • (function() { x=5; 1+2+3; }).toString() == function() { x=5; }
Community
  • 1
  • 1
Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • @delnan - Various objects override the `object.toString()` method, in the case of functions you get the full function text :) – Nick Craver Jul 31 '10 at 21:41
  • I knew js was very dynamic, reflective, has first-class functions, etc. But this is... well, I don't know if it's awesome or unnecessary bling-bling. A mix of both, I guess. –  Jul 31 '10 at 21:43
  • The formatting is a function of the environment you're working in - things like Chrome's JS console or Firebug's console add the formatting. – Amber Jul 31 '10 at 21:52
  • @delnan - For the sake of carrying on the bling, there are other less-used properties as well, `derp.length === 0` for the number of arguments, `derp.name === "derp"`, you can `.apply()` or `.call()` it for use in closures (mainly but not exclusively), etc...there is a lot of JavaScript `function`...well, functionality that most people writing it never come across. It's unfortunate, because there's a lot in there, and it's really useful in many cases. – Nick Craver Jul 31 '10 at 21:53
  • 1
    `name` is non-standard and isn't supported in all browsers. Notable non-supporters include (would you believe) IE. – Tim Down Jul 31 '10 at 22:00
  • 3
    @Nick, This will work on almost all browsers, but maybe is worth mentioning that the `Function.prototype.toString` method returns an "*implementation-dependent* representation of the function", and in some implementations (Opera Mobile and Older Safari versions IIRC) it will not return the source code of the function, also the `name` property on function objects is *non-standard*. – Christian C. Salvadó Jul 31 '10 at 22:02
  • @CMS, @Tim - I'm aware it's non-standard, just showing some possible properties, which is why it's in a comment not an answer :) In case anyone's interested in the above you can easily see what is/isn't cross-browser here: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function – Nick Craver Jul 31 '10 at 22:04
  • @CMS - The `.toString()` should be safe for current usage if you're using it for display purposes, the spec says it should have the syntax of a function declaration: `function Identifier (FormalParameterList) { FunctionBody }`. So though it's implementation dependent it *should* (as of ECMAscript v3) look like pretty much like the above (with differences in white-space mainly). If a browser (e.g. older Safari) doesn't follow the spec...I tend to see that as the browser's fault. – Nick Craver Jul 31 '10 at 22:23
  • It is worth noting that Firefox returns a partially "compiled" version of the body of the function that strips comments, extra whitespace, extra semicolons, and anything else it consideres useless. For instance, `(function() { x=5; 1+2+3; }).toString()` returns `"function () { x = 5; }"`. Most amusingly however is `function() { x=5+4; }` would be returned as `"function () { x = 9; }"` – MooGoo Jul 31 '10 at 22:42
  • 2
    @Nick, yes but I think the specification should be more formal, in almost all implementations, the spec. then is not *strictly followed*, for example, an anonymous `FunctionExpression`, like `(function() {}).toString()` returns a string that does *not* represent the grammar of a `FunctionDeclaration`: `"function () {}"`, the mandatory `Identifier` token is missing... BTW I've found the issues where Opera Mobile made [PrototypeJS](http://j.mp/a8cyVa) and [jQuery fail](http://j.mp/bv9yOs). – Christian C. Salvadó Aug 01 '10 at 00:38
  • @CMS, @Tim, @Moo - Thanks for the comments and examples, I updated the answer to include (hopefully) everything relevant to this question in hopes it gets more eyes than the comments here, these are all great examples to be aware of...if you feel it needs editing go ahead :) – Nick Craver Aug 01 '10 at 04:16
  • Firefox doesn't seem to display the compiled function string anymore. Tested on Firefox versions 41 and 89. – mcmimik Jun 11 '21 at 17:15
10
function derp() { a(); b(); c(); }

alert(derp.toString());
CD..
  • 72,281
  • 25
  • 154
  • 163