I heard the speaker in a meetup say, “You’re either evil, or just plain stupid if you use eval in your code”.

Is there are any grain of truth behind the above statement?

Write your answer…

3 answers

I think it's one of those superstitious things that's based on truth where there is an element of truth to it, and because of this people avoid it religiously without understanding why. But just because somebody knows avoid it without knowing why doesn't mean they're wrong to avoid it. But it sure does make it difficult to ask questions about it and learn how to use it correctly.

I've recently been working with eval() and another even more hated JavaScript function: with(), over the past couple of weeks so I'll share what I've learned.

I have a plugin that was built using eval() and with() each one time, so I wanted to see if I could refactor the plugin in a way that it would behave the same, but avoid the use of those two functions.

When to use eval()

Just about any time you even mention eval() in the presence of other programmers, you will often by met with comments like:

"No matter what you think you need it for, you probably don't need it"

"Just never use eval()"

"If you're using eval() you've got bigger problems in your code to worry about"

"90% of the time you can rewrite your code to not use eval()"

And even: "For your stated use case there is no need to use eval()" …even when there was no stated use case mentioned 😜

It turns out many beginners find eval() when googling problems while stuck trying to do something, and when using eval() works they think they've solved their problem so they consider it fixed and continue on. However, in many of these beginner cases the eval() is overkill, will make their script perform slower, and introduce the possibility of some new bugs that are really hard to track down and debug. For these reasons we should always be hesitant before we use eval() and explore solutions that perform better!

It seems the only good use-case for eval() is interpreting JavaScript code contained within another language. Let's say you have some raw text, and some of that text is JS, you could use eval() to turn the quoted JavaScript back into JavaScript and execute it. When that is the task you need to do, eval() is the only thing that will work, but it's very rare that you're needing to execute quoted JavaScript code from another language (and this should be done with caution when you do).

When not to use eval()

For any use case where the thing you are trying to do is not taking a piece of quoted JavaScript code out of raw text. For all other purposes there are better ways to implement what you want to do that will be easier to debug and work with in the future.

Why did I need eval()

I work with a custom CSS syntax that allows me to add JavaScript code inside my stylesheets, and the plugin that reads these styles needs to extract the JavaScript code and then run it as JavaScript in order to arrive at the result I want. I also needed to use with(), an even more-hated JavaScript function, to evaluate the JavaScript code from the context of the element to which the styles are applying. It's a really neat, very specific need, and as much as I (and others) tried, there was no way to reimplement the same functionality without using eval() and with().

What are the downsides of using eval()?

Some JavaScript programmers much smarter than me told me that when the JavaScript rendering engine looks at a function that contains eval() (or with()) it is not able to make optimizations about that function because it has no idea (can't predict) the scope of what might be run through it. You could also evaluate code that changes global code elsewhere, so there's no way you can guess what will happen ahead of time. This means that any function containing eval() runs in 'deopt' mode, which lacks the optimizations the browser is able to make with other JavaScript.

Because of this, in my plugin I decided to isolate just the part of the function previously containing eval() and put that into in its own function. Now my larger function is able to run with optimizations, and it's only the tiny function containing eval() that runs in the slower 'deopt' mode.

Here's what I ended up doing:

/*
 * Eval('') and $it
 * (…yes with() was necessary, and eval() too!)
 */

EQCSS.tryWithEval = function(element, string) {
  var $it = element;
  var ret = "";
  try {
    with ($it) { ret = eval(string.slice(1, -1)) }
  }
  catch(e) {
    ret = "";
  };
  return ret;
}

You can see I left a comment for all the curious people coming after me wondering if it's really necessary, and if I couldn't just refactor it to not use eval() or with(). In this case, they are truly unavoidable, but that is a rare thing.

To learn more about how eval() works, check out this article, it really helped me: https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

Cup1
Clap1
Cool1
1 Beer1

Hashnode is building a friendly and inclusive dev community. Come jump on the bandwagon!

  • 💬 A beginner friendly place

  • 🧠 Stay in the loop and grow your knowledge

  • 🍕 >500K developers share programming wisdom here

  • ❤️ Support the growing dev community!

Register ( 500k+ developers strong 👊)

Here are some problems

A)Any variables declared in the eval code can pollute the lexical scope . It might shadow the variables that are declared outside the eval as well . It creates global variables and pollutes the scoping model

B)the code is hard to debug

C) Your code becomes slow . Javascript compiler initially does a single pass compilation before running the code . However in case of eval it is compiled and run only in the run time

D)Any malicious code can end up being "eval" ed

Alternatives to eval :

https://www.npmjs.com/package/vm

as @balajive mentioned.

but ! ;D ... actually a lot of libs do it anyway .... otherwise you can not parse and bootstrap injected script tags for example.

or you could use function http://stackoverflow.com/questions/20129236/creating-functions-dynamically-in-js

but in general don't overuse eval. I try to avoid is as often as I can, but sometimes you need to write selfgenerating code where eval comes in handy.