JavaScript Function Syntax
Learn the "new Function" syntax in JavaScript: how to build functions from strings at runtime, its scope rules, and security trade-offs versus eval.
Most of the time you create a function with a declaration, an expression, or an arrow function. But JavaScript has one more way: the new Function constructor, which builds a function from strings at runtime. This page focuses on that syntax — its exact form, the scope rules that surprise most developers, how it compares to eval, and the narrow set of cases where it is the right tool.
The new Function Syntax
The new Function syntax lets you create a function whose parameters and body are supplied as strings. Because the body is just text until the engine parses it, you can assemble a function whose code is not known when you write your program — only at the moment it runs.
The general form is:
let func = new Function([arg1, arg2, ...argN], functionBody);Every argument is a string. The first arguments name the parameters; the last argument is always the function body.
You can pass all parameter names in a single comma-separated string, which is equivalent:
The new keyword is optional here — Function('a', 'b', 'return a + b') produces the same result — but writing new Function(...) is the conventional, clearer form.
Why It Exists
The main thing that makes new Function different from a normal declaration is that the body comes from a string. That string can be received from anywhere: a server response, a template, user configuration, or text you build up at runtime. So the syntax exists for exactly the cases where the code you want to run does not exist yet when you write the program.
Scope: the Big Gotcha
This is the detail that trips everyone up. A function created with new Function does not capture the scope where it was created. Unlike a normal closure, its outer lexical environment is the global scope, not the local one.
function makeAdder() {
let outer = 100;
// This function tries to read `outer`...
return new Function('x', 'return x + outer');
}
const add = makeAdder();
add(5); // ReferenceError: outer is not definedA regular function written the same way would happily close over outer. The new Function version cannot — it only sees its own parameters and the global scope:
This is intentional. If new Function could reach local variables, minifiers (which rename outer to a, secret to b, and so on) would break any code that referenced those names as strings. By restricting access to the global scope, the language keeps minification safe. The practical takeaway: pass everything a dynamic function needs through its arguments, never expect it to read surrounding variables.
Properties of a Dynamic Function
A function built this way is a normal function object in every other respect, with one quirk — its name is always "anonymous":
That empty-ish name is one reason dynamic functions are harder to read in stack traces — see the debugging note below.
new Function vs. eval
Both new Function and eval turn strings into running code, but they behave very differently:
eval(str)runsstrin the current scope, so it can read and even modify nearby local variables. That tight coupling makes it harder to optimize and easier to misuse.new Functionis isolated from local scope (as shown above) and gives you back a reusable function rather than a one-off evaluation.
For the rare case where you genuinely need to run code from a string, new Function is the safer of the two because its blast radius is limited to the global scope and its explicit parameters.
Practical Applications and Examples
Below is a complete, runnable example you can edit and execute in the browser.
Advanced Insights into Dynamic Function Creation
Dynamic function creation in JavaScript, facilitated by the new Function syntax, is a powerful technique that allows developers to construct functions from strings of code at runtime. This capability is particularly useful in scenarios where the code to be executed is not static or known ahead of time, such as in applications that require a high degree of flexibility or in situations where scripts are generated or modified dynamically. In this section, we'll delve deeper into the mechanics, benefits, and considerations of dynamic function creation, offering a richer understanding and practical examples to illustrate its potential.
Mechanics of Dynamic Function Creation
The new Function syntax creates a new function instance. The arguments to the new Function constructor are strings representing the function's arguments, followed by a string representing the function's body.
This functionally equates to declaring a function in the traditional manner, but with the key difference being the ability to assemble the function's code dynamically, at runtime.
Benefits of Dynamic Function Creation
- Flexibility and Customization: Dynamic function creation allows for a high degree of customization, as functions can be generated based on user input, configuration settings, or other runtime data.
- Scripting and Templating: It's particularly useful in implementing custom scripting solutions or templating engines where the template logic needs to be evaluated at runtime.
- Isolation and Security: When used carefully, it can execute code in a more controlled environment, potentially isolating the dynamically executed code from the main application context.
Considerations and Best Practices
While dynamic function creation is powerful, it comes with its set of considerations:
- Security: The primary concern is security. Since the function code is constructed from strings, there's a risk of executing malicious code if the input is not properly sanitized. Always validate and sanitize input that will be used to generate function code.
- Performance: Dynamically created functions can be less performant than their statically declared counterparts, as the JavaScript engine must parse the function body string each time a new function is created. Use this feature judiciously, especially in performance-critical paths.
- Debugging: Debugging dynamically generated functions can be more challenging, as the code does not exist until runtime. Providing meaningful names to dynamically created functions can help mitigate this issue.
- Lexical Scope Limitation: Functions created with
new Functiondo not capture the local scope where they are defined. They only have access to global variables and their own parameters. This can lead toReferenceErrors if you expect them to access outer variables. (See the Scope section above; pass data in through arguments.)
Advanced Example: A Simple Templating Engine
To illustrate the practical use of dynamic function creation, consider the implementation of a simple templating engine. This engine will replace placeholders in a template string with values from a data object — and, crucially, the data is passed in as an argument, working around the scope limitation.
Note: The \${ sequence escapes the template literal syntax. This prevents the ${expr} placeholder from being evaluated immediately, ensuring it is passed as a literal string to the generated function body.
This example demonstrates not only the flexibility offered by dynamic function creation but also highlights the importance of careful construction and sanitization of the input to avoid security risks.
Summary
The new Function constructor builds a function from strings at runtime:
let func = new Function([arg1, ..., argN], functionBody);Key points to remember:
- The last argument is always the function body; the earlier ones name the parameters.
- A dynamically created function's outer scope is global, not the place it was created — it cannot close over local variables, so pass data through arguments.
- It is generally safer than
eval(which runs in the current scope), but both evaluate strings, so only ever feed it trusted, sanitized input. - Use it for genuinely dynamic code — templating engines, sandboxed expression evaluators, runtime-generated handlers — and prefer ordinary functions or arrow functions everywhere else.
To go deeper on related topics, see JavaScript Closures, Variable Scope, and Function Expressions.