A Deep Dive into JavaScript's new Function Syntax

Each section shows a small piece of code, then runs the same idea directly below it. The examples focus on where string-built functions are powerful, and where their scope rules surprise people.

1. Basic Syntax: Arguments First, Body Last

The final string becomes the function body. Every earlier string becomes a named parameter.

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

return sum(a, b);
Result:

2. Turn an Object-Like String into JSON

JSON.parse() rejects unquoted keys, but JavaScript can still evaluate this as an object literal.

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

return JSON.stringify(new Function('return ' + str)());
Result:

3. Use ES Template Strings as a Template Engine

The template body is a string. new Function turns the placeholders and expressions inside it into executable template syntax.

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

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

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

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

return html;
Result:

4. No Closure: The Function Body Uses Global Scope

A function created with new Function cannot see local variables from the place where it was created.

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

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

  return func;
}

return getFunc()();
Result:

5. Regular Functions Do Capture Local Variables

A normal function keeps access to the surrounding lexical scope, so it can read value.

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

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

  return func;
}

return getFunc()();
Result:

6. Similar Idea: Dynamic Regular Expressions

new RegExp also accepts strings, which is useful when a pattern is assembled at runtime.

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

return samples.map(function (sample) {
  return {
    text: sample,
    matches: reg.test(sample)
  };
});
Result: