However, these worthy scenarios make up a tiny percentage of the actual usage of eval. In the majority of cases, eval is used like a sledgehammer swatting a fly -- it gets the job done, but with too much power. It's slow, it's unwieldy, and tends to magnify the damage when you make a mistake. Please spread the word far and wide: if you are considering using eval then there is probably a better way. Think hard before you use eval.
Let me give you an example of a typical usage.
<span id="myspan1"></span>
<span id="myspan2"></span>
<span id="myspan3"></span>
<script language="jscript">
function setspan(num, text)
{
eval("myspan" + num + ".innerText = '" + text + "'"); }
</script>
Somehow the program is getting its hands on a number, and it wants to map that to a particular span. What's wrong with this picture?
Well, pretty much everything. This is a horrid way to implement these simple semantics. First off, what if the text contains an apostrophe? Then we'll generate
myspan1.innerText = 'it ain't what you do, it's the way thacha do it';
Which isn't legal JScript. Similarly, what if it contains stuff interpretable as escape sequences? OK, let's fix that up.
eval("myspan" + num).innerText = text;
If you have to use eval, eval as little of the expression as possible, and only do it once. I've seen code like this in real live web sites:
if (eval(foo) != null && eval(foo).blah == 123)
eval(foo).baz = "hello";
Yikes! That calls the compiler three times to compile up the same code! People, eval starts a compiler. Before you use it, ask yourself whether there is a better way to solve this problem than starting up a compiler!
Anyway, our modified solution is much better but still awful. What if num is out of range? What if it isn't even a number? We could put in checks, but why bother? We need to take a step back here and ask what problem we are trying to solve.
We have a number. We would like to map that number onto an object. How would you solve this problem if you didn't have eval? This is not a difficult programming problem! Obviously an array is a far better solution:
var spans = new Array(null, myspan1, myspan2, myspan3);
if (spans[num] != null)
spans[num].innertext = text;
}
And since JScript has string-indexed associative arrays, this generalizes to far more than just numeric scenarios. Build any map you want. JScript even provides a convenient syntax for maps!
var spans = { 1 : mySpan1, 2 : mySpan2, 12 : mySpan12 };
Let's compare these two solutions on a number of axes:
Debugability: what is easier to debug, a program that dynamically generates new code at runtime, or a program with a static body of code? What is easier to debug, a program that uses arrays as arrays, or a program that every time it needs to map a number to an object it compiles up a small new program?
Maintainability: What's easier to maintain, a table or a program that dynamically spits new code?
Speed: which do you think is faster, a program that dereferences an array, or a program that starts a compiler?
Memory: which uses more memory, a program that dereferences an array, or a program that starts a compiler and compiles a new chunk of code every time you need to access an array?
There is absolutely no reason to use eval to solve problems like mapping strings or numbers onto objects. Doing so dramatically lowers the quality of the code on pretty much every imaginable axis.
It gets even worse when you use eval on the server, but that's another post.
PingBack from http://www.belshe.com/2006/10/25/disection-of-a-spam-comment/
Eval is easy... Hahahahahahah.
If a fly is bugging me and I have a sledgehammer beside me, why go inside for and search for a flyswatter? That might take me half an hour.
Also:-
Debugability. Well if bugs turn up I can always rewrite it the hard way. Also in many cases the eval code may be simpler and more readable.
Maintainability. Depends on the situtaion. Eval may be better.
Speed. If it's fast enough who cares.
Memory. Aint a problem.
I think a lot of of "Gurus" are opposed to anything that makes life easier for us lesser beings.
Steve Rocks!
I agree, a religious conception of programming is the whorthest evil there is (bracket should be opened on a new line, etc);
Though, going back to the eval thing, it is true that the eval is bad and that there is a number of workarounds (one of the reasons why i love js!).
Workaround A: gotta call a method of an object but i know only the name.
doing eval('obj.' + methodName) seems a piece of cake. What about obj[methodName]() ? Much better.
Though there is nothing like:
function ClassFactory(constructorClassName){
var myObj;
eval('myObj=new ' + constructorClassName +'()')
return myObj;
A class factory on the fly!!!
PingBack from http://blog.roberthahn.ca/articles/2007/02/02/how-to-use-window-onload-the-right-way
PingBack from http://rayfd.wordpress.com/2007/03/28/why-wont-eval-eval-my-json-or-json-object-object-literal/
PingBack from http://www.tutorials.de/forum/php/268678-template-engine-3.html#post1415829
--- QUOTE ---
--- END QUOTE ---
How about:
--- CODE ---
function ClassFactory(constructorClassName) {
return new this[constructorClassName]();
--- END CODE ---
(Although the usefulness of this function is debatable, and the names misleading: there are no classes in JScript.)
Almost* everything that can be done with eval() can be done with square bracket notation, and not only is it more efficient, it's also almost invariably simpler (you don't have to worry about whether the input will form a valid JS expression, for a start) and produces neater code than eval():
try {
eval('myobject.' + propName + ' = ' "' + propValue + '"');
} catch(e) {}
// versus
myobject.someProperty[propName] = propValue;
Especially note, if we're discussing getElementById() support, that some older browsers don't support try/catch, so the only option when given a bad property name or value is to error out if you want to support these browsers.
* I say "almost" -- the example scenarios EricLippert gave are perfectly valid reasons to use eval(), and to write a dedicated JS parser for these situations is (usually) silly when eval() is already available.
P.S. Ugh, I had to switch browsers to post this -- no Konq support on a blog that deals with web coding?
PingBack from http://deviweb.wordpress.com/2007/09/03/5-things-i-hate-about-ruby/
PingBack from http://codeutopia.net/blog/2007/11/03/the-best-smarty-zend-view-helpers-solution/
PingBack from http://www.ajaxgirl.com/2008/01/26/is-using-a-js-packer-a-security-threat/
PingBack from http://www.javascriptnews.com/javascript/is-using-a-js-packer-a-security-threat.html