6 min read

A Deep Dive into JavaScript’s `new Function` Syntax

Table of Contents

Cover Image

Most JavaScript developers rarely need new Function.

In day-to-day frontend or Node.js work, a regular function or arrow function is usually clearer, safer, and easier to maintain:

const sum = (a, b) => a + b;

So why does JavaScript still have the Function constructor?

Because it can do something ordinary functions cannot: it creates executable JavaScript from a string.

That single capability makes new Function both powerful and dangerous.

The Basic Syntax

The syntax looks like this:

let func = new Function([arg1, arg2, ...argN], functionBody);

The final argument is always the function body. Every argument before it becomes a named parameter.

Here is the simplest example from the demo:

let sum = new Function('a', 'b', 'return a + b');

const result = sum(1, 2);
console.log(result); // 3

The strings 'a' and 'b' become function parameters. The string 'return a + b' becomes the function body.

Conceptually, JavaScript turns that into something close to this:

function anonymous(a, b) {
  return a + b;
}

The difference is that the function body was built dynamically at runtime.

Why This Matters

The important feature is not the syntax itself. The important feature is this:

new Function lets you execute JavaScript code stored inside a string.

That makes it useful in cases where the program logic is not fully known until runtime.

Examples include:

  • converting object-like strings into real JavaScript objects
  • building small template engines
  • generating dynamic expressions
  • evaluating controlled configuration logic
  • sandbox-like demos and developer tools

But this power comes with a serious warning: never run strings from untrusted users with new Function. It can execute arbitrary JavaScript.

Converting an Object-Like String into JSON

Suppose we have this string:

let str = `{ "id": 10393, name: 'zhangxinxu', 'date': '2022-04-30' }`;

It looks like JSON, but it is not valid JSON.

The key name is not wrapped in double quotes, and one value uses single quotes. JSON.parse() will reject it.

However, JavaScript itself can evaluate this as an object literal. That is where new Function can help:

let str = `{ "id": 10393, name: 'zhangxinxu', 'date': '2022-04-30' }`;

const result = JSON.stringify(new Function('return ' + str)());

console.log(result);
// {"id":10393,"name":"zhangxinxu","date":"2022-04-30"}

The function body becomes:

return { "id": 10393, name: 'zhangxinxu', 'date': '2022-04-30' }

Then the generated function is executed immediately.

This is concise, but it should only be used with trusted input. If str comes from a user, API, database, or third-party source, this becomes a code execution vulnerability.

Using Template Strings as a Tiny Template Engine

Another powerful use case is template rendering.

Modern frameworks like Vue, React, and Svelte all provide their own ways to render data into markup. But with new Function, you can also turn native JavaScript template literals into a small template system.

Here is the core idea from the demo:

String.prototype.interpolate = function (params) {
  const names = Object.keys(params);
  const vals = Object.values(params);

  return new Function(...names, `return \`${this}\`;`)(...vals);
};

This method takes an object like:

{
  data: [
    { article: 'Article Title 1', author: 'Zhang Xinxu' },
    { article: 'Article Title 2', author: 'CSS New World' }
  ]
}

Then it exposes each key as a variable inside the generated function.

For example, data becomes available inside the template string:

const template = `${data.map(function (obj) {
  return `<article>
  <p>Article: ${obj.article}</p>
  <p>Author: ${obj.author}</p>
</article>`;
}).join('')}`;

const html = template.interpolate({ data });

console.log(html);

This produces a final HTML string by running real JavaScript expressions inside the template.

This is effectively a tiny template engine built from native JavaScript.

Again, the safety rule matters: this is only appropriate when the template content is trusted.

The Scope Surprise: No Closure

One of the biggest gotchas with new Function is scope.

A function created with new Function does not close over local variables from the place where it was created.

For example:

function getFunc() {
  let value = 'zhangxinxu';

  let func = new Function('return value');

  return func;
}

getFunc()(); // ReferenceError: value is not defined

The generated function runs in the global scope. It cannot see the local value variable inside getFunc.

A regular function behaves differently:

function getFunc() {
  let value = 'zhangxinxu';

  let func = function () {
    return value;
  };

  return func;
}

getFunc()(); // "zhangxinxu"

This difference is crucial.

Regular functions capture lexical scope. Functions created with new Function do not.

new Function is not the only JavaScript constructor that accepts strings.

new RegExp also lets you build behavior dynamically:

let reg = new RegExp('^' + value, 'g');

const result = samples.map(function (sample) {
  reg.lastIndex = 0;

  return {
    text: sample,
    matches: reg.test(sample)
  };
});

This is useful when the pattern depends on runtime data, such as matching values that start with a dynamic prefix.

The key difference is that new RegExp creates a regular expression, while new Function creates executable code. The security implications of new Function are much larger.

When Should You Use new Function?

Use it rarely.

Good use cases include:

  • controlled developer tools
  • trusted template compilation
  • educational demos
  • dynamic expression systems where inputs are carefully validated
  • libraries that intentionally compile strings into optimized functions

Avoid it when:

  • a regular function works
  • the string comes from a user
  • the code path handles sensitive data
  • the behavior can be represented as data instead of executable code

Final Thoughts

new Function is not useless. It is one of JavaScript’s most powerful runtime metaprogramming tools.

Its strength is also its risk: it turns strings into executable JavaScript.

Used carefully, it can power template engines, dynamic evaluators, and clever transformation utilities. Used carelessly, it can create severe security vulnerabilities.

For most application code, prefer regular functions. But when you truly need to generate executable logic from a trusted string, new Function is a tool worth understanding.


Try It Yourself

Want to see these concepts in action? I’ve created an interactive demo where you can experiment with the code and see real-time results.

View the Live Demo

Explore more demos from my previous articles in the Demo Gallery.

Happy coding!