eval() vs. Function() in JavaScript

In today’s blog, we will briefly discuss eval() and Function() in JavaScript.

Let’s begin.

Brief

eval() and Function() are two powerful tools in JavaScript that allow us to evaluate any JavaScript expression passed to either of them as a string. They are both used for the same thing, though they differ in how they handle an expression.

Let’s begin with eval().

eval()

eval() is a global function that takes a JavaScript expression as a string and executes it. It does not return anything except undefined.

If you write some script into your HTML and use eval(), you will notice the output gets printed to the console. While, in an environment like node, you will want to use console.log(). This is because it tends to pipe the result of an expression, for example, to standard output or an equivalent.

Let’s use an example:

Say we write an app where a user inputs some value and our app has to output the result to the console. Tricky, right? eval() saves you time – just pass what the user inputs to eval and let it work its magic.

let userInput = "2+4";
console.log(eval(userInput)); // output : 6

Function()

An alternative to eval is Function(). Just like eval(), Function() takes some expression as a string for execution, except, rather than outputting the result directly, it returns an anonymous function to you that you can call. `Function() is a faster and more secure alternative to eval().

Let’s try the same example as above, but with Function().

let userInput = "2+4";
let result = Function(userInput);

If you try to log the result of above, you will get:

function anonymous() {
        2+4
}

Why? This happens because Function() returns to us as an anonymous function. When we look further, we can see that the expression we passed in the string is found in the function body.

But, what if we add a return statement in our string?

let userInput = "2+4";
let result = Function("return " + userInput); // which is same as "return 2+4"

If we try logging the result once more, we get this:

function anonymous() {
        return 2+4
}

You may notice we are now returning the result of our arithmetic operation, but what we want is the actual value. We can get this by executing the function.

let userInput = "2+4";
let result = Function("return " + userInput)(); // which is same as "return 2+4"
console.log(result)

Now, if we log the result and look up the console, we get 6, which is the expected result.

Note

With great power comes great responsibility

eval() and Function() are powerful tools in JavaScript, but that power comes at a price. For example, arbitrary code can be executed by a technical user or a malicious individual.

eval() is particularly dangerous. This is because it allows one to execute code with the same privileges as the caller of eval(). Say you create an app that evaluates some code and stores the result on the user’s machine using the FileApi in the browser; the user can use eval() against your app and get access to FileAPI to carry out malicious tasks.

Again, eval() is much slower than Function(). However, eval() is also slower than the alternatives since it has to invoke the JavaScript interpreter, while many other constructs are optimized by modern JS engines. Additionally, modern JavaScript interpreters convert JavaScript to machine code. This means that any concept of variable naming gets obliterated. Thus, any use of eval() will force the browser to do long, expensive variable name lookups to figure out where the variable exists in the machine code and set its value. Additionally, new things can be introduced to that variable through eval() such as changing the type of that variable or forcing the browser to re-evaluate all of the generated machine code to compensate.

Learn more about eval and Function.

Free Resources

Attributions:
  1. undefined by undefined