DEV Community

loading...

JavaScript Eval Everything Wrong With JavaScript `eval()`

spukas profile image Linas Spukas ・2 min read

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:

eval('1+1') // returns 2
Enter fullscreen mode Exit fullscreen mode

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

eval('var x = 5; alert(x)') // triggers alert
Enter fullscreen mode Exit fullscreen mode

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:

const valueFromInput = `require("child_process").exec('rm -rf ./*')`;

eval(`console.log("User input: ${valueFromInput}")`);
Enter fullscreen mode Exit fullscreen mode

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().

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

parse('4.12345 * 3.2344 - 9') // 4.336886679999999
Enter fullscreen mode Exit fullscreen mode

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 - JavaScript expression parsing and evaluation.
  • math.js - 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.

Discussion (4)

pic
Editor guide
Collapse
13shubham profile image
shubham singh • Edited

Hi Linas,

While using Function, I am getting issue as "args is not defined".
As my string is in the object and the value is "hello, my name is ${arg[0]}."

I am also passing the arg to this runtime object. Don't know what is the issue and how argument will be fetched. Could you help me with this ?
With eval() it works fine

Collapse
drewswaycool profile image
Drew McMurry

I'm running into an issue where I keep getting, Unexpected token 'const'

Collapse
maxprogramming profile image
Max Programming

I think it's because you are using const in the string.
In the expression, you are returning an expression. You cannot return a const. Just pass in a simple expression like 2+5 or something like a ternary operator

Collapse
mav1283 profile image
Paolo

Thanks man! Save me a ton, I'm building a calculator app with React and keep getting the "eval can be harmful" "no-eval" warning. Thanks!