Sergio and the sigil

JavaScript: Avoid the Evil eval

Posted by Sergio on 2009-03-31
This post is part of a series called JavaScript Demystified.

I'm pretty sure by now you have heard at least once that eval is evil. Some nuggets from Eric Lippert's post:

if you are considering using eval then there is probably a better way
People, eval starts a compiler.

I'm also pretty sure I don't need to tell you that anytime you have an explicit eval() in your code, there's a good chance it's there because you're not taking JavaScript seriously yet.

//mandatory square brackets notation example
//------------------------------------------
var myObject = new MyObject();
var prop1 = eval( 'myObject.' + somePropertyName ); // BAD!
var prop2 = myObject[ somePropertyName ]; // Better

That's not the end of all eval()

At this point some people might be feeling relieved: "Phew! That was easier than it sounded. Getting rid of eval is a piece of cake." Well, I'm not going to say it's significantly harder than that, but we're not done prunning eval() from our code just yet.

You see, eval() is like that coward opponent that sneaks in the dark to attack you from behind. Let's find some of eval's favorite hiding places.

There's a time when you need a timer

Two very popular JavaScript functions used to create timers are setTimeout() and setInterval(). Here's how you still find code being written to use them.

function doSomething(someValue){
	//...
}

setTimeout("doSomething('3 seconds elapsed. Time is up.');", 3000);

As it turns out, this is just another occurrence of eval() revealing how incompetent we can still be in this programming language. Here's a better way to write that code.

setTimeout( function(){ 
                doSomething('3 seconds elapsed. Time is up.');
            }, 
            3000);

Thank God I didn't know functions had constructors

The other secret place that eval() likes to hang out is in the Function constructor. Fortunately this isn't exactly a popular way of creating functions. I'll say it: I didn't even know about this constructor until less than a couple of years ago.

So, in case you don't know what I'm talking about here, I'll show you how to use the function constructor just to imemdiately tell you to not do it.

var sum = new Function('op1', 'op2', 'return op1 + op2;');
var result = sum(10, 20); // ==> 30

The above code is roughly equivalent to the explicit eval() usage below.

eval("var sum = function (op1, op2) { return op1 + op2; }");
var result = sum(10, 20); // ==> 30

We don't come up with the need to use the function constructor often, but I'll admit that when we do, it's usually hard to replace it with another way that doesn't use eval().

Minor update: I was doing some snooping around with Firebug and Reflector and found that WebUIValidation.js (embedded in System.Web.dll) does use eval() in some ways that I just pointed out to be unnecessary. If that is of any comfort to anyone that has done the same in the past, there you have probably the largest deployment of misused eval() I know of.