- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Well, eval is actually useful in cases where you want to share a set of common functions from other .js files. It's a workaround for the absense of #include in JS.
Admin
Maybe fStr had more than that, initially, and they never refactored after removing the part that necessitated an eval().
The empty (and therefore unnecessary) else {} clause in that eval string seems to indicate that there used to be more code.
Admin
<i>Well, eval is actually useful in cases where you want to share a set of common functions from other .js files. It's a workaround for the absense of #include in JS. </i>
<script language="JavaScript" type="text/javascript" src="js/utils.js"/>
Why can't you use that instead of #include? It does the same thing. Eval is not necessary in this case neither.
Admin
I don't care if this is refactored or not--just because it might be leftover from something else doesn't prevent it from looking stupid.
Admin
I work where that came from - trust me, the guy (a contractor) did a lot of weird shit. After he left the team he was part of went about purging his code.
Admin
Heh, I like how fStr is properly indented.
Admin
Johnie: JS can exist apart from a web page. HTML is not a subset of JavaScript.
Of course, there's no standard file I/O for JS, either, so how do you read this "included" file? With five lines of code involving some overly-orthogonal WSH object, I guess...
I can't remember the last time I saw eval() used in a way that made any sense at all; most of its fans seem to be web developers who write eval('foo.'+bar) instead of foo[bar]. I have no idea why they do that, and I'm sure I'll sleep more soundly if I never find out.
Admin
row = document.createElement('TR');
for(var i=0; i < COLUMNS.length; i++)
{
cell = document.createElement('TH');
var onclick_act = 'sort_col(' + i + ');';
eval('cell.onclick = function () { ' + onclick_act + '};');
cell.appendChild( document.createTextNode(COLUMNS[i]) );
row.appendChild(cell);
}
thead.appendChild(row);
Admin
A few notes:
The backslash serves as a line-continuation character, so that could be
var fStr = "blah
blah blah
blah blah
blah blah";
Though obviously the eval is completely unnecessary to begin with.
You can actually programmatically create functions in JavaScript from a string without using eval by doing this:
var f = new Function(arg1, ... , argN, bodyString);
so replace
eval('cell.onclick = function () { ' + onclick_act + '};')
with
cell.onclick = new Function(onclick_act);
Admin
I find cleaver how he deals with the well-known javascript' bug that puts an unwanted char at the end of an empty string.
Admin
Well, the Function constructor is about as incorrect as the use of eval. Both tend to destroy the maintainability of code that employs them, and both have the potential to open you up to cross-site scripting attacks if you aren't careful.
Admin
eval has its uses, but... you can rewrite today's 'wtf' these ways:
1)
httpRequest.onreadystatechange = function () {
if (nCrossings && 4==httpRequest.readyState) callback(httpRequest);
};
2)
httpRequest.onreadystatechange = howdydoody;
function howdydoody () {
if (nCrossings && 4==httpRequest.readyState) callback(httpRequest);
}
Admin
X, that does not need eval nor the Function constructor (which is just as bad, you're recompiling [yes, js compiles to bytecode] at runtime). You can do this instead (irrelevant parts removed):
for(var i=0; i < COLUMNS.length; i++)
{
var cell = document.createElement('TH');
cell.myIndex = i;
cell.onclick = sort_col;
}
And in sort_col simply use this.myIndex to get what used to be 'i'. This will yield much better performance too.
Another option is to use closures and return a real function reference, for example:
for(var i=0; i < COLUMNS.length; i++)
{
var cell = document.createElement('TH');
cell.onclick = getRef(i);
}
And getRef:
function getRef(index) {
return function () { sort_col(index); }
}
This will also improve performance greatly and is more "correct" than using another property on the cell, but will require you to clean up references yourself or lose some in-page memory.
Regardless, eval is completely unnecessary in your example.
Admin
as I see it, the code is snipped out of a functino that has a function 'callback' as a parameter.
So eval is used here to provide late binding.
There might be other ways, but just writing those lines inside the eval string into the source directly wouldn't work!
Guenter
Admin
Guenter: Wrong, it would work fine with the eval removed and putting those lines in the source directly. JS is already late bound, you don't need to force that using eval.
Admin
JavaScript is one of those mysterious things that people don't know much about. Kind of like microwave ovens and non-dairy creamer. :)
Admin
I don't like what the commenting system has become.
These people are always trying to outsmart someone with their "actually"s and "this is another way of doing it, look at my 1337 coding skills".
Well guess what, I'm not interested. People who can't understand the code couldn't give a fuck if you could write a better implementation.
On the other hand, the people who can code will understand the code and how to implement it better without you trying to be smart and posting about it.
I really didn't think I would ever say this, but: "GET A FUCKING LIFE!".
This site would be better with the commenting off, but on the other hand it would be nice if people could comment when they really need to.
I hate it when some idiots ruin good stuff.
Admin
You know pompo500, it's just as easy for you to simply ignore the comments and pretend they're not there ...
Admin
pompo:
1. No one is forcing you to read the comments, if you rather have comments off, simply don't read them, it's almost the same!
2. No one is trying to outsmart anybody, people make mistakes and other people either correct them or start a discussion over it. It happens everywhere and it's just another way for people learn in this business.
3. If there's anything that bothers me, it's people with inferiority complexes who whine when someone takes the time to write up an educated comment, in order to help developers realize common mistakes and misconceptions instead of leaving them in their ignorance.
To those I would say "GET A FUCKING LIFE AND TRY TO HELP INSTEAD OF WHINING". I suggest you take your own advice and only comment when you have something intelligent to say.
Admin
I have learned A LOT by reading these comments. Some of the solutions that the people have provided are considerably more clever than anything than I would have come up with. I consider myself a good coder, better than a lot of people I know, and that isn't saying much. You can always learn something from someone else. They may have just come up with a slightly more elegant solution to a problem and you are "Wow"-ed. So pompo...I'm going to jump on the "Get A Life!" bandwagon. These comments are awesome. If it were really an issue, I believe that more than just you would have complained.
Admin
Ok, I'm confused. If we're not to comment on the code, or how we would do it better, or how the original author may have had the right idea, what are we to comment on?
"Hehe. He has a function that begins with makeLog. Doodoo."
Ah, now that's more my speed. No more of this smart stuff, OK guys?
Admin
X, yn: What Jay is saying is that you need a closure. Lucky you! You've got them whether you want them or not.
Closures are "function objects", or "instances" of functions which carry their context along with them. In JavaScript, all functions do this. Therefore, you don't need to convert the local variable i into a constant with eval(); i will remain eternally in scope for your anonymous function in any case.
cell.onclick = function () { sort_col( i ); };
This looks like the kind of thing a really naive beginning programmer might think would work. The funny thing is, it actually DOES work in some languages.
An even funnier thing is what it implies about the stack in the implementation: When you can have two instances of the same scope "alive" at the same time, their relationship to their enclosing scope is more problematic than the usual if-inside-an-if sort of thing where you just set aside some extra space on the stack and get on with your life.
http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?activation+record
Admin
...actually a better comparison would've been to a function call in C: It's more problematic than that, too.
Admin
Aarrgghh, not quite, your example wouldn't work in his case. Your closure is in the loop-containing function, which means that when any of the anonymous functions is executed 'i' will always be equal to the last value in the loop (COLUMNS.length) and NOT to the value at the time of assignment (the anonymous function retains parent function scope, never block-level [loop] scope).
This is why you have to either use another function to contain the closure in the correct scope of the loop value and return it OR a property, like i've shown.
Admin
Bu, Nice Pinky and the Brain reference!
Pinky: What do you want to do tonight, Brain?
Brain: The same thing we do every night. Try to code up the world!
Admin
yn: Oops! You're right on all counts. It'll be the same i for everybody in that case. I didn't pay attention to your function-currying suggestion, either.
Admin
I'd like to thank those who commented on my example, especially yn. JavaScript isn't my main specialty, having mostly been pushed into it through dealing with CGI, and what I've found while trying to learn more is a mess of bad examples, old references, and cross-browser madness.
What I pasted was part of a proof-of-concept for a future project (one I'm frankly glad is a bit in the future because of Mozilla's non-stable Array.sort() implementation), and I tried a few things before settling on eval(). It felt like cheating, but it worked.
And Aarrgghh, your suggestion was one of the things I tried, and I quickly moved on after discovering it would always sort by the last column. ;)
Admin
I LOVE the comments on here. Part of what makes the daily WTF good is that it's great fun to watch folks justifying (potentially) bad code.
Sadly the ISBN one I can't actually justify EVER.
The "smart arse" comments are brilliant and show great ingenuity in trying to explain WHY some code exists. We all know that in reality 99.9% of the time the original programmer was just f**king stupid.
Believe me I used to do support for Borland Turbo C 1.0 & 1.5 and some of the clangers that turned up in my mailbox were astounding. Step 1 in that job was to turn on ALL compiler warnings, fix them first usually found the problem in 5 minutes flat. BTW Worst first day of a product shipping ever, chapter 1(or is it zero?) in K&R has a farenheit to celcius program which used floating point constants, the bit of the compiler that folded 9.0/5.0 into 1.8 didn't and instead did it back to front.
Admin
Although this thread slants toward the negatives of how eval can be used, I've found it practical to use when evaluating dynamically generated expressions as in the following example.
This code will permute all combinations using numDigits of theDigit with operators [+ - * /] and output all that match checkNum.
For instance...
calculateExpressions(8, 8, 8248);
...says use eight eights and find all permuted expressions that equate to 8248...
8888+888-8 = 8248
888+8888-8 = 8248
8888-8+888 = 8248
888-8+8888 = 8248
<pre>
function calculateExpressions(numDigits, theDigit, checkNum)
{
var theOps = "+-*/"; // (the absence of an operator is included by code)
var numOps = theOps.length;
var opPos = new Array(numDigits);
if(isNaN(numDigits) || numDigits < 2 || numDigits > 8 || isNaN(theDigit) || isNaN(checkNum))
{
alert("All values must be numbers and 'Number of digits' must be between 1 and 9");
}
else
{
for(i = 1; i < numDigits; i++) opPos[i]=0;
theOuterLoop:
while (1)
{
theExpression = theDigit;
for (i = 1; i < numDigits; i++)
{
theExpression += theOps.substr(opPos[i], 1) + theDigit;
}
var theAnswer = eval(theExpression);
if (theAnswer == checkNum) document.writeln(theExpression + " = " + theAnswer + "<br>");
i = 1;
opPos[i]++;
while (opPos[i] > numOps)
{
if (i == (numDigits - 1)) break theOuterLoop;
opPos[i] = 0;
opPos[++i]++;
}
}
document.close();
}
}
</pre>
Admin
Actually, my favorite portion of this code lies in:
//alert(fStr);
As if he needed to ensure that static the string he just created could possibly be anything other than what was just typed.
Admin
I have also found eval() to be very useful. I have have done programming most of time with Flash actionscript where eval() function is quite necessary.
I had a problem, where you selected images from database in a form of dropdown menu and when selecting one item in menu, it updates preview-image next to it. In one page those image selection -dropdown-menus can exist from 1 to 6 (or even more if you want). I created JavaScript function where when calling it you can specify the count of image selection -drop down-menus. This count is created dynamically with PHP-loop which searches necessary counts to be used.
--------------------------------
function imgsel(i){
var update = 'document.images.preview'+i+'.src= document.article.image'+i+'.options[document.article.image'+i+'.selectedIndex].value';
if (!document.images)
return
eval (update);
}
----------------------
dropdown-menus has following dynamic attributes: ($i is loop iteration)
<select name="image$i" size="1" onChange="imgsel($i)">
option values are URLs to image.
onChange Attribute calls JavaScript-function with $i
Which is updating image next to it:
<img src="$whatever" name="preview$i">
If someone could tell me better way to do that (without eval()?), i would appreciate it a lot.
-Nemezec