In this article, we will explore the eval() method. We will get to know the syntax and explain what is the purpose of the method. We will explore whether eval() is really evil and whether you should really stop using it. And if it’s not, are there any legitimate reasons when you should use the eval() method.
What is eval() method in JavaScript?
eval() method was first featured in ES1 – it dates way back in 1997, therefore it is fully supported in all browsers. Its syntax is simple:
eval(string)
As you can see in the syntax presented above – the parameter of the eval() method is a string – a JavaScript expression, variable, statement, or sequence of statements. The keyword eval serves as an abbreviation for “evaluate”, and what it does is the function essentially takes a string with JavaScript code and evaluates it. Thus, the purpose of the eval() method is to evaluate or execute an argument:
- When the argument is an expression, eval() evaluates the expression.
- When the argument is one or more JavaScript statements, eval() executes the statements.
At this point, it is important to bring out that you should not call eval() to evaluate an arithmetic expression because JavaScript evaluates arithmetic expressions automatically. Therefore, when a string is constructed with arithmetic expression, evaluation through an eval() method can be used later in your script. For instance, with an eval() method, you can delay the evaluation of some expression by assigning the string value of the expression and then calling eval() at a later point in your script. However, if eval()’s argument is not a string, eval() method will return the argument unchanged.
eval() as a function property of the global object
Starting from ECMAScript 5, when using eval() method indirectly – invoking it through reference other than eval() – the method does not work in the local, but global scope instead. What does that mean? That means that when functions are declared they create global functions, and the code that is evaluated doesn’t have access to local variables within the scope where it’s being called.
So, why is eval so bad and should you really stop using it?
There are several reasons you should avoid using eval() or at least use it carefully. Let’s take a look at them.
1. eval() creates problems with debugging
This problem was actually more of a problem 10 years ago – back then, it was actually impossible to approach code with eval() in it. Luckily, Chrome Developer Tools worked this way around and nowdays it is possible to debug code that contains eval(). However, there are still problems with a normal development flow. Yes, compared to almost 10 years ago, you can view and go through the code, but you have to wait until the code executes before it will show up in the Source panel. For this reason, eval() could create problems with debugging, but essentially it is not the main reason you should stop using it.
2. eval() creates problems with a performance
Performance in terms of speed is a big issue with eval(). The eval()’s parameter is a string, but Javascript is meant to use a larger scope of types, including numbers, functions, and objects and not just strings.
When code contains eval(), Javascript engine reads the code as unpredictable. For this reason, the code is run in the interpreter, which causes double interpretation, just like with the old school browsers, and this makes a huge impact on the performance speed. This results in up to ten times slower outcomes compared to the code that does not contain eval(). A big reason to find an alternative to eval(), don’t you think?
3. eval() creates problems with renaming variables
In addition to the double interpretation and therefore a speed issue, eval() causes problems with the YUI compressor to convert variable names that are in the scope of the call to eval(). eval() has a great ability – it can access directly any of the variables. However, a problem occurs when you would want to rename any of these variables because renaming them would cause errors. Even tools that convert variable names could still cause errors, so renaming variables still presents an issue that is hard to avoid with eval().
4. eval() creates problems with security when users control the input
Last, but not least. eval() posses a security risk, but don’t take this as a general rule of thumb.
When working within a scope of XXS attacks, using eval() opens your code to these attacks because eval() executes arbitrary code in the context of the page and yes, it is dangerous when you take the user’s input and run it through eval(). Therefore, never ever do that – take the user’s input and somehow pass it through eval(). On the other hand, if your code has nothing to do with the user’s inputs and you’re the only one who controls the input, using eval() should not pose any security risk.
5. eval() creates problems with security in terms of man-in-the-middle attacks
Another important eval() security problem is connected to the code that is returned from the server, which is especially the case with JSON because the code can be quickly converted into JavaScript by using eval(). These days, however, most coders use the built-in JSON parsing capabilities of browsers for this purpose. Some developers still fetch arbitrary JavaScript to execute via eval() as part of a lazy-loading strategy, and this exactly could be the real security vulnerability. In a scenario when a man-in-the-middle attack is in progress, you will be executing arbitrary attacker code on the page. This scenario can be seen as one of the main dangers of using eval() because it makes the code susceptible to worms. However, advanced coders understand that if you can’t trust the server you’re contacting, many other malicious things are possible and man-in-the-middle attacks could inject code onto the page in any number of ways. If this is the case, you have bigger problems to deal with than calling eval() here and then. This said, using eval() doesn’t pose any bigger risk to the man-in-the-middle attacks than loading JavaScript externally.
Are there any legitimate reasons you should use eval()?
In the paragraphs above we’ve looked into a few cases when using eval() does not make your code so fragile after all, especially if you understand when you can use it. At the end of the day, there are problems with debugging, performance and security, especially when users control the input. But, let’s see if there are any legitimate reasons when you should use eval() after all.
To be honest, there are very few reasons and good use cases you should use eval(), and most of them are meta-programming and build tools, such as developing:
- template libraries,
- interpreters,
- command lines,
- module systems.
In most cases, a good alternative to eval() is Funtion(), which just like eval() takes a string for execution from an expression. However, there is a small, but important difference. eval() will output the result directly, but a Function() will return an anonymous function to you which you can later call.