Skip to content

Instantly share code, notes, and snippets.

@lamberta
Created September 23, 2012 03:57
Show Gist options
  • Star 55 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save lamberta/3768814 to your computer and use it in GitHub Desktop.
Save lamberta/3768814 to your computer and use it in GitHub Desktop.
Parse a JavaScript string function definition and return a function object. Does not use eval.
/* Parse a string function definition and return a function object. Does not use eval.
* @param {string} str
* @return {function}
*
* Example:
* var f = function (x, y) { return x * y; };
* var g = parseFunction(f.toString());
* g(33, 3); //=> 99
*/
function parseFunction (str) {
var fn_body_idx = str.indexOf('{'),
fn_body = str.substring(fn_body_idx+1, str.lastIndexOf('}')),
fn_declare = str.substring(0, fn_body_idx),
fn_params = fn_declare.substring(fn_declare.indexOf('(')+1, fn_declare.lastIndexOf(')')),
args = fn_params.split(',');
args.push(fn_body);
function Fn () {
return Function.apply(this, args);
}
Fn.prototype = Function.prototype;
return new Fn();
}
@jasonswearingen
Copy link

nice, works with lambdas too.

@atharhashmi
Copy link

atharhashmi commented Nov 19, 2019

This is probably the most underrated utility on the entire GitHub. Pity that such a helpful utility has got just 9 stars!

@raulrojasadl
Copy link

Thanks!!!

@oeway
Copy link

oeway commented Feb 18, 2021

Thanks for sharing!

I did some modification to support async function:

function parseFunction (str) {
  const is_async = str.trim().startsWith('async'),
      fn_body_idx = str.indexOf('{'),
      fn_body = str.substring(fn_body_idx+1, str.lastIndexOf('}')),
      fn_declare = str.substring(0, fn_body_idx),
      fn_params = fn_declare.substring(fn_declare.indexOf('(')+1, fn_declare.lastIndexOf(')')),
      args = fn_params.split(',');
  args.push(fn_body);
  
  if(is_async){
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    function Fn () {
      return AsyncFunction.apply(this, args);
    }
    Fn.prototype = AsyncFunction.prototype;
  }
  else{
    function Fn () {
      return Function.apply(this, args);
    }
    Fn.prototype = Function.prototype;
  }
  return new Fn();
}

@mholtzhausen
Copy link

Does not work with destructured function parameters (es6) :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment