W3docs

JavaScript eval()

Learn how JavaScript's eval() function runs a string as code. Covers syntax, return value, security risks, and safer alternatives.

JavaScript can turn a string into running code at runtime. The built-in eval() function does exactly that: it takes a string, treats it as JavaScript source, and runs it. This page explains how eval() works, where it returns a value, why it is almost always the wrong tool, and what to reach for instead.

This page covers:

  • The syntax of eval() and what it returns.
  • Real use cases (and why most of them have better alternatives today).
  • The security and performance problems that make eval() dangerous.
  • Safer replacements: the Function constructor and JSON.parse().
  • Best practices for the rare cases where you genuinely need it.

Understanding the eval() Function

eval() evaluates or executes a string of JavaScript code. If the string is an expression, eval() evaluates it and returns the result. If the string is one or more statements, eval() runs them and returns the value of the last expression statement (or undefined).

Syntax

eval(string)

Parameters:

  • string — a string of JavaScript source code to evaluate.

Return value: the result of the last expression evaluated, or undefined if the string contains no expressions.

If string is not a string (for example a number), eval() returns the argument unchanged.

Example Usage

In this example we evaluate a simple arithmetic expression and print the result:

javascript— editable

Practical Use Cases for eval()

While the eval() function can be immensely powerful, its use is often discouraged due to security and performance concerns. However, there are scenarios where eval() can be useful.

Dynamic Code Execution

In situations where code must be generated and executed dynamically, eval() can be a practical solution. For instance, creating a calculator that evaluates user input as a mathematical expression:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Dynamic Calculator</title>
</head>
<body>
    <p>Add any arithmetic expression like 12 + 5 and hit 'Calculate' button!</p>
    <div>
        <input type="text" id="expression" placeholder="Enter expression" /> <!-- User input field -->
        <button onclick="evaluateExpression()">Calculate</button> <!-- Button to trigger calculation -->
    </div>
    <div id="calcResult"></div> <!-- Element to display result -->
    <script>
        function evaluateExpression() {
            const expression = document.getElementById('expression').value; // Get user input
            try {
                const result = eval(expression); // Evaluate the expression
                document.getElementById('calcResult').textContent = `Result: ${result}`; // Display the result
            } catch (e) {
                document.getElementById('calcResult').textContent = 'Invalid expression'; // Handle invalid input
            }
        }
    </script>
</body>
</html>

Parsing JSON with eval()

Before the introduction of JSON.parse(), eval() was used to parse JSON strings. However, it is now recommended to use JSON.parse() due to security concerns.

javascript— editable

When using eval() to parse JSON strings, it's crucial to ensure that the JSON string is interpreted as an object expression rather than a block statement. To achieve this, the JSON string is wrapped within parentheses before passing it to eval(). This ensures that JavaScript treats the string as an object expression, preventing syntax errors that could occur if the string were interpreted as a block statement.

Info

Always prefer JSON.parse() over eval() for parsing JSON. JSON.parse() only accepts data, so it can never run an injected script.

Direct vs. Indirect eval and Scope

How eval() sees variables depends on how you call it.

A direct call — eval(code) written literally — runs the code in the current scope. It can read and even create variables where it is called:

javascript— editable

An indirect call — calling eval through any reference other than the literal name, such as (0, eval)(code) or storing it in a variable — runs the code in the global scope instead. It cannot see local variables:

javascript— editable

In strict mode, even a direct eval() gets its own scope: variables it declares do not leak into the surrounding function. This is one more reason modern code rarely needs eval().

Security and Performance Concerns

Using eval() can pose significant security risks and performance issues. Here’s why:

Security Risks

eval() can execute any JavaScript code, making it vulnerable to injection attacks. An attacker could potentially inject malicious code, leading to severe security breaches.

Example of Security Risk:

Imagine you have a web application that takes user input and evaluates it using eval(). Without proper validation, this can be exploited by an attacker to execute malicious code.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>eval() Security Risk Example</title>
</head>
<body>
    <div>
     <p>Hit 'Run Code' button!</p>
        <input type="text" id="userInput" placeholder="Enter code" value="alert('Hacked!')" /> <!-- User input field -->
        <button onclick="evaluateUserInput()">Run Code</button> <!-- Button to run code -->
    </div>
    <div id="userInputResult"></div> <!-- Element to display result -->
    <script>
        function evaluateUserInput() {
            const input = document.getElementById('userInput').value; // Get user input
            try {
                const result = eval(input); // Evaluate the user input
                document.getElementById('userInputResult').textContent = `Result: ${result}`; // Display the result
            } catch (e) {
                document.getElementById('userInputResult').textContent = 'Error in evaluation'; // Handle evaluation error
            }
        }
    </script>
</body>
</html>

In this example, if a user enters something like alert('Hacked!'), the eval() function will execute it, causing a security breach by displaying an alert box. An attacker could inject more harmful code, potentially compromising the entire system.

Performance Issues

eval() executes code in the same scope from which it’s called, hindering JavaScript engine optimizations. This can lead to slower performance compared to other approaches.

Example of Performance Issue:

Let's consider a scenario where we need to perform a series of calculations multiple times. Using eval() for this task can significantly impact performance.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Performance Issues with eval()</title>
</head>
<body>
    <div id="evalResult"></div>
    <div id="functionResult"></div>
    <script>
        // Using eval()
        const evalStartTime = performance.now();
        for (let i = 0; i < 100000; i++) {
            eval("3 * 4 + 5");
        }
        const evalEndTime = performance.now();
        const evalDuration = evalEndTime - evalStartTime;
        document.getElementById('evalResult').textContent = `Time taken with eval(): ${evalDuration} ms`;

        // Using Function constructor
        const func = new Function('return 3 * 4 + 5');
        const funcStartTime = performance.now();
        for (let i = 0; i < 100000; i++) {
            func();
        }
        const funcEndTime = performance.now();
        const funcDuration = funcEndTime - funcStartTime;
        document.getElementById('functionResult').textContent = `Time taken with Function constructor: ${funcDuration} ms`;
    </script>
</body>
</html>

In this example, we compare the performance of eval() with the Function constructor. We execute a simple arithmetic operation (3 * 4 + 5) 100,000 times using both methods and measure the time taken for each.

  • Using eval(): The code inside eval() is evaluated repeatedly, which is slower because it prevents certain optimizations.
  • Using Function Constructor: The Function constructor creates a function that performs the same operation, but it's faster because it allows JavaScript engines to optimize the repeated execution.

The results displayed on the webpage show the time taken by each method, demonstrating that eval() is slower due to its performance issues.

Warning

Avoid eval() unless absolutely necessary. Reach for safer alternatives first: the Function constructor for dynamic functions, or JSON.parse() for data.

Alternatives to eval()

For safer and more efficient code execution, consider the following alternatives:

Using Function Constructor

The Function constructor creates a new function object, similar to eval(), but with better security and performance.

javascript— editable

Using JSON.parse()

For parsing JSON strings, JSON.parse() is the preferred method.

javascript— editable

Best Practices for Using eval()

If you must use eval(), adhere to these best practices to mitigate risks:

1. Validate Input

Ensure the input to eval() is strictly validated to prevent code injection. This means allowing only safe characters and expressions.

Example:

javascript— editable

In this example, we use a regular expression to validate the user input. Only numeric characters and basic arithmetic operators are allowed. If the input matches the pattern, it is evaluated with eval(). Otherwise, it is rejected as invalid.

2. Use Try-Catch

Wrap eval() in a try-catch block to handle potential errors gracefully. This prevents the entire application from crashing if eval() encounters an error.

Example:

javascript— editable

Here, we handle syntax errors in the user input using a try-catch block. If eval() throws an error, it is caught, and an error message is logged instead of crashing the application.

3. Restrict Scope

Minimize the scope of variables accessible to eval() to limit potential damage from malicious code. Use an immediately invoked function expression (IIFE) to create a local scope.

Example:

javascript— editable

In this example, we define a function restrictedEval inside an IIFE to create a local scope. This function evaluates the input using eval() but with locally defined variables a and b. The global variables a and b are not accessible, demonstrating scope restriction.

By following these best practices, you can reduce the risks associated with using eval() while still leveraging its dynamic code execution capabilities when necessary.

Conclusion

The eval() function in JavaScript provides a powerful tool for dynamic code execution, but it comes with significant risks and performance drawbacks. In practice almost any task that seems to need eval() has a safer answer: use JSON.parse() for data, the Function constructor for dynamic functions, and object/array lookups instead of building variable names from strings. If you must use eval(), validate input, wrap it in try...catch, and keep its scope as small as possible.

Practice

Practice
What does the eval() function in JavaScript do?
What does the eval() function in JavaScript do?
Was this page helpful?