# JS string to function without evaluating

**URL:** <https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055>\
**Category:** programming\
**Created:** [June 24, 2021, 1:24pm UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055 "2021-06-24T13:24:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![steve.mills](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/steve.mills/32/14961_2.png) [@steve.mills](https://forum.kirupa.com/u/steve.mills)\
**Post date:** [June 24, 2021, 1:24pm UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/1 "2021-06-24T13:24:38Z")

</div>

Hey guys,  
I recently wanted to dynamically convert a string to a function and store it without evaluating (JS, not production code).  
After a few problems , I came across this Github gist:

> <https://gist.github.com/lamberta/3768814>

It didn’t do generators so did my own version with async generators/generators.

If you have need for it its pretty easy to use, just make sure you use `"` not `'` and you cant use `=>` (prototype problem).  
You also cant `"use strict"` as it generates a `new Function`.

Summing up `parseFunction` can generate any function like:  
`let parsed = parseFunction("function(){return 123}")` will equate to  
`// let parsed = anonymous function(){return 123};`  
`parsed() // returns 123`

My version with async and generators:

```
function parseFunction (str) {
  const   
      index = str.indexOf('{'),
      tindex = str.indexOf('(') 
      body = str.substring(index+1, str.lastIndexOf('}')),
      dec = str.substring(0, index),
      type = str.substring(0, tindex),
      params = dec.substring(dec.indexOf('(')+1, dec.lastIndexOf(')')),
      args = params.split(',');
      isAsync = str.trim().startsWith('async'),
      isGenerator = type.trim().endsWith('*'),
        
  args.push(body);
  
  if(isAsync && isGenerator){
    const AsyncGeneratorFunction = Object.getPrototypeOf(async function*(){}).constructor;
    function Fn () { return AsyncGeneratorFunction.apply(this, args);}
    Fn.prototype = AsyncGeneratorFunction.prototype;
  }
  else if(isAsync){
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    function Fn () { return AsyncFunction.apply(this, args);}
    Fn.prototype = AsyncFunction.prototype;
  }
  else if(isGenerator){
    const GeneratorFunction = Object.getPrototypeOf(function*(){}).constructor;
    function Fn () { return GeneratorFunction.apply(this, args);}
    Fn.prototype = GeneratorFunction.prototype;
  }
  else{
    function Fn () { return Function.apply(this, args);}
    Fn.prototype = Function.prototype;
  }
  return new Fn();
}
```

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [June 25, 2021, 4:33am UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/2 "2021-06-25T04:33:27Z")

</div>

Wow! That is really cool. This is something that @senocular and @krilnon would find fascinating.

---

<div class="post-metadata">

**Author:** ![steve.mills](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/steve.mills/32/14961_2.png) [@steve.mills](https://forum.kirupa.com/u/steve.mills)\
**Post date:** [June 25, 2021, 6:47am UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/3 "2021-06-25T06:47:58Z")

</div>

Where it gets super useful is dynamic template literals.e.g.

```javascript
var x = 1;
myObj = { lit1: () => `the value of x is ${x}`};
myObj.lit1() //returns 'the value of x is 1'
 x = 5;
myObj.lit1() //returns 'the value of x is 5;

```

Well with something like this (based on the gist)

```javascript
const dynLit = function(x) {
  let y = `return ${x}`;
  let dynLit = function () {return Function.call(this,y)};
  dynLit.prototype = Function.prototype;
  return new dynLit();
}

```

You could do this:

```javascript
myObj.lit2 = dynLit(" ${x} is not x");

```

and update myObj:

```javascript
myObj = {  
    lit1: () => `the value of x is ${x}`,
    lit2: anonymous function() {return `${x} is not x`}
};

```

Now you can actually dynamically build objects and templates (with JS) that can use template literals and update when required…

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [June 27, 2021, 1:19am UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/4 "2021-06-27T01:19:38Z")

</div>

This can be done more simply and with fewer limitations by just running the string through the function constructor and returning the result. So basically:

```javascript
function parseFunction (str) {
  return Function(`return ${str}`)()
}

```

In fact this works for any source code expression, not just functions

```javascript
let parsed = parseFunction("() => {return 123}")
parsed() // returns 123
let parsedNum = parseFunction("456")
parsedNum // 456

```

The original gist is going to run into problems trying to parse the function into its individual parts depending on how that function is defined. For example what happens when you have a default parameter assigned to an object literal?

```javascript
let parsed = parseFunction("function(x = {}){return 123}")
// parse failure in finding first "{"

```

JavaScript already knows how to parse the function fully, so you can let it handle all of that and simply return the value in full from a host function who’s only job is to evaluate and return the result of the code (not _be_ the actual function itself). This is also forward compatible since no parser needs to be updated for future JS features. Its all dependent on the runtime itself which already knows what it supports and how to parse it. So out of the box it works for arrow functions, generators, async, and everything else, as well as everything to come (like maybe [generator arrow functions](https://github.com/tc39/proposal-generator-arrow-functions)).

---

<div class="post-metadata">

**Author:** ![steve.mills](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/steve.mills/32/14961_2.png) [@steve.mills](https://forum.kirupa.com/u/steve.mills)\
**Post date:** [June 27, 2021, 3:47am UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/5 "2021-06-27T03:47:29Z")

</div>

cool… I didn’t even realize you could call the function constructor without `new Function`. I’m definitely going to use this. Thanks

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [June 27, 2021, 2:22pm UTC](https://forum.kirupa.com/t/js-string-to-function-without-evaluating/648055/6 "2021-06-27T14:22:04Z")

</div>

> [@steve.mills](#):
>
> cool… I didn’t even realize you could call the function constructor without `new Function`

That’s what the original code was doing with `return Function.apply(this, args)` and the async/generator variants 😉
