Everything Wrong With JavaScript `eval()`
Tags: javascript, eval
Published: 2019-10-27 17:46:04

This week I had the pleasure to get to know more about the infamous `eval()` function, as it was my first instinct to use it for arithmetic evaluation. We ended up using a third-party library for that matter, but I'd like to shed some light on that topic.

So `eval()` is a global Javascript function that evaluates a string as a command. If a string represents an expression, the function will evaluate it as an expression:

```js
eval('1+1') // returns 2
```

and if it is a statment or a sequance of statements, it will evaluate the last statement:

```jsx
eval('var x = 5; alert(x)') // triggers alert
```

Also, I need to mention that `eval()` uses the scope in which it is called.

## Risks

The main reason you should avoid using it is a **security**. Evaluating JavaScript code from a string is hazardous. A string may consist of malicious code that will be run on the user's machine, and the scope, where `eval()` was called will be exposed for possible attacks.
Especially it is dangerous if you try to evaluate the user's input, that can lead to infinite loops, deleting files or steeling administrative cookies.
For example evaluating the string in Node.js would delete all the files in the current directory:

```jsx
const valueFromInput = `require("child_process").exec('rm -rf ./*')`;
 
eval(`console.log("User input: ${valueFromInput}")`);
```

The second reason is **performance**. Calling `eval()` will be slower than using alternatives, because it has to call JavaScript interpreter, which will convert evaluated code to the machine language. That means if you run the code more than once, the browser will have to interpret the same code again, which is highly inefficient.
Moreover, changing the type of the variable through `eval()` will force the browser re-run the code. And using variables that are not in scope with `eval()` will require for the browser to do an expensive lookup to check whether the variable exists. 

## Alternatives
The most simple alternative is to use `windows.Function()`. It creates a global scope function from the string. This way, you can write your custom parser to evaluate the code from the string. It is less likely for the possible attacks to do harm comparing with `eval()`.

```jsx
function parse(str) {
  return Function(`'use strict'; return (${str})`)()
}

parse('4.12345 * 3.2344 - 9') // 4.336886679999999
```
In the example above, we are creating a function from the string using strict mode. Which makes it easier to write "secure" JavaScript, for example, you can't use undeclared variables.

Other alternatives that do not use `eval()`:
- [expression-eval](https://www.npmjs.com/package/expression-eval) - JavaScript expression parsing and evaluation.
- [math.js](https://www.npmjs.com/package/mathjs) - Extensive math library for JavaScript and Node.js

## Sum Up

`eval()` function is rarely used in the modern JavaScript because of its high vulnerability and performance reasons. Misusing the function can lead to running malicious code on the user's machine and data loss. There are third-party alternatives that will fool-proof a string evaluation to JavaScript, and for simple usage, you can use global `Function()` to write your own custom evaluation function.