eval()
eval(string) The eval() function evaluates JavaScript code represented as a string and returns the result of executing that code. It is one of the oldest and most powerful features of JavaScript, but also one of the most dangerous when misused.
Syntax
eval(string)
Parameters
| Parameter | Type | Description |
|---|---|---|
string | string | A string representing a JavaScript expression, statement, or sequence of statements. |
Return Value
The result of evaluating the given code. If the string is empty, it returns undefined. If the code throws an error, that error is propagated to the caller.
Examples
Basic Usage
eval("2 + 2");
// 4
const x = 5;
eval("x * 2");
// 10
eval("JavaScript".toUpperCase());
// "JAVASCRIPT"
The examples above show arithmetic and method calls — eval() evaluates any expression that could appear on the right side of an assignment. It also handles comparisons and function return values, which makes it useful for computing conditions from string input.
Evaluating Expressions
eval("Math.sqrt(16)");
// 4
eval("10 > 5");
// true
Single expressions are straightforward. When you pass multiple statements separated by semicolons, eval() executes them in sequence and returns the value of the last one — just like a function body would, allowing you to declare variables and compute a final result in one call.
Executing multiple statements
eval("const a = 10; const b = 20; a + b");
// 30
Multi-statement evaluation acts like an inline script embedded in your code. You can also use eval() to resolve property paths built at runtime, giving you dynamic access to object fields without the bracket notation you would otherwise need for computed property names.
Dynamic property access
const obj = { name: "Alice", age: 30 };
eval("obj.name");
// "Alice"
const prop = "age";
eval("obj." + prop);
// 30
Dynamic property access saves you from writing explicit bracket notation. The same principle extends to operating on entire data structures — eval() can construct and transform arrays and strings directly from string input, executing method chains and callbacks inline.
Working with Arrays
eval("[1, 2, 3].map(x => x * 2)");
// [2, 4, 6]
eval("'abc'.split('')");
// ["a", "b", "c"]
The examples so far show eval() working with strings you control. The moment those strings come from an external source — user input, a query parameter, or a message from another system — eval() becomes a code execution vector. The next section explores what that risk looks like in practice.
Security Concerns
Using eval() is generally discouraged due to security and performance issues. Understanding these risks is crucial for writing secure JavaScript applications.
Code injection risk
// DANGEROUS: Never use eval() with untrusted input
const userInput = "console.log('hacked')";
eval(userInput); // Executes arbitrary code!
Alternatives for different use cases
Most situations that tempt you toward eval() have a safer tool designed specifically for the job. The three alternatives below cover dynamic function creation, data parsing, and string assembly — each with far less risk than running arbitrary code.
Alternative: Function constructor
// Safer alternative for simple expressions
const add = new Function("a", "b", "return a + b");
add(2, 3);
// 5
The Function constructor creates functions from strings but runs in a separate scope, so it can’t access local variables — a useful built-in safety limitation. When your goal is simply to turn a JSON string into a usable JavaScript object, JSON.parse() is faster, safer, and purpose-built for the task.
Alternative: JSON Parsing
For structured data like API responses and config files, eval() is never the right tool. JSON.parse() is a single-purpose parser that rejects anything that isn’t valid JSON — it won’t execute functions or access variables, eliminating the injection surface entirely.
// For parsing JSON, use JSON.parse() instead of eval()
const json = '{"name": "Alice", "age": 30}';
JSON.parse(json);
// { name: "Alice", age: 30 }
JSON.parse() handles structured data cleanly and rejects anything that isn’t valid JSON. For string assembly — the most common reason developers reach for eval() — template literals provide interpolation without any execution risk and with full editor support for syntax highlighting and autocomplete.
Alternative: Template literals
// Instead of eval() for dynamic strings, use template literals
const name = "World";
const greeting = `Hello, ${name}!`;
// "Hello, World!"
Template literals handle string interpolation at parse time with full syntax highlighting and autocomplete support in every modern editor. Beyond the obvious security concerns, eval() also carries a measurable performance penalty that matters noticeably in tight loops and frequently called hot code paths.
Performance Implications
The eval() function is significantly slower than alternatives because it must invoke the JavaScript interpreter at runtime. Every call to eval() forces the engine to compile and execute new code, bypassing many optimizations that the JIT compiler normally applies to static code. This overhead becomes especially visible inside loops where each iteration triggers a fresh parse and compile step.
// Slow: Using eval() in a loop
for (let i = 0; i < 1000; i++) {
eval("x = " + i);
}
// Faster: Direct code
for (let i = 0; i < 1000; i++) {
x = i;
}
When eval() might be necessary
There are rare cases where eval() is the only practical solution:
- Dynamic code generation from trusted sources
- JSON parsing of deeply nested structures (though
JSON.parse()is preferred) - Macro systems that generate code at runtime
- Legacy code that cannot be refactored
Even in these cases, carefully validate and sanitize any input before passing it to eval().
Why eval() Is Risky
eval() is powerful because it turns text into executable code, but that power is also why it is dangerous. Any string that reaches it can change the behavior of your program, which means a bug or injection flaw can become code execution. That is a much higher risk than parsing data or calling a known function.
It also makes the code harder to reason about. Static analysis, minification, and optimization all become less reliable when the runtime can invent new code paths from strings. Even trusted input can cause maintenance problems because readers have to inspect the string separately from the call site.
Safer Alternatives
Most uses of eval() have a direct replacement. Use JSON.parse() for JSON, a lookup table for dynamic property access, template literals for string assembly, and Function only in tightly controlled code generation scenarios. Those tools keep the intent visible and reduce the chance that untrusted data turns into executable instructions.
If you truly need runtime evaluation, treat the input like code review material. Keep the source narrow, sanitize it carefully, and isolate the feature so the rest of the application does not depend on it.
See Also
- Function constructor — Alternative for creating functions dynamically from strings
- JSON.parse() — Safe way to parse JSON data without executing arbitrary code
- Math.sqrt() — Square root function as an alternative to parsing with eval