“eval is Evil: The eval function is the most misused feature of JavaScript. Avoid it” Douglas Crockford in JavaScript: The Good Parts

I like The Good Parts. It’s essential reading for anyone who’s serious about JavaScript – and I realize that Crockford’s goal here is to emphasize only what he likes – but still I think that such a brief yet total rejection might send the wrong message.

Let’s consider the arguments most frequently leveled against using eval:

1) It requires a compile and is therefore slow

2) What if a malicious script found its way into the eval argument?

3) It looks ugly

4) It inherits the execution context and this binding of the scope in which its invoked

The slowness thing is a matter of common sense – and needs a sense of perspective. All JavaScript gets compiled when it is loaded into the browser. When I launch my app it loads 500K of script in a fraction of a second, so evaluating a few more lines later on will be a trivial hit. Even IE8 will eval 1000 lines of assignments in a few milliseconds. This is not to say performance should never be a consideration when using eval – but that consideration should include a dose of reality.

What about security? If its your software that’s supplying eval with its argument then there’s very little to fear on this front. Sure, it would be unwise to eval the value of an input box, but running eval over a response generated by your own server code should present no special risk. Also bear in mind there is no damage a would-be-attacker could do with client side eval that they couldn’t more easily achieve with a modern browser console.

The ugliness argument is hard to disagree with. Hard coded eval arguments are difficult to read and don’t co-operate with auto-formatters. I don’t see any reason to use eval with hard coded parameters – this also applies to the eval-wrappers: setTimeout and the Function constructor.

//eval version - hard to read setTimeout('sendRequest(' + actionName + ',' + validate + ')', 1000); //better setTimeout(function() {sendRequest(actionName, validate)}, 1000); //best (see <a href="https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/">curry</a>) setTimeout(sendRequest.curry(actionName,validate), 1000);

As for eval sharing the caller’s execution context – I’m not convinced its either a good or a bad thing – its just something you need to know.

So when is it ok to use eval? No two coding situations are alike, and sometimes an unorthodox approach turns out to be the best one. Understanding the pros and cons of an approach will get you much further in the long run than blindly adhering to someone else’s checklist of dos and don’ts.

That said, it makes a lot of sense to use eval when it is necessary to parse response strings from your server into JSON or other JavaScript. But don’t just take my word for it: both Prototype’s evalJSON and JQuery’s parseJSON use eval…so you might be using eval in your code even as you argue against it :-).

Interesting sidenote: ECMA 5 introduced a native JSON.parse function (not yet supported in all browsers. JSON). The JSON.parse specification was modelled after the json2.js implementation written by Douglas Crockford. Take a look at the code – there is eval, right there on line 469. It’s just too useful!

// In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')');

JQuery uses the Function constructor as a wrapper to the eval call (presumably so that the evalled code will not execute in the local context). In simplified form it goes something like this:

var evalJSON = function(theJSON) { //check for well formed JSON //.. //use native JSON parser (ECMA 5) if available... //...otherwise construct a function that returns the JSON and run it immediately... new Function("return " + theJSON)(); //this does an eval. }

Prototype opts for the more direct approach (and it performs better). Sanitize is called optionally and verifies the JSON is well formed

evalJSON: function(sanitize) { var json = this.unfilterJSON(); //strips comment delimiters try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); }

JQuery prefers the Function constructor over a direct eval call since this will perform an eval in the global scope. None-the-less the heavy reliance of the major frameworks on the eval function should make even the most hardcore eval naysayer think twice.

Moreover, without eval there would be no developer tools.

So how evil is eval? It’s as evil as you make it. Use it with care, but use it if you need to – you’ll be in good company.

“Overwhelmingly [eval is] trivailized, misused, and outright condemned by most JavaScript programmers but by looking at the work of some of the best coders you can see that , when used appropriately [it] allows for the creation of some fantastic pieces of code that wouldn’t be possible otherwise” John Resig in Secrets of the JavaScript Ninja