RFD: How To Recognize Bad Javascript Code

  • Thread starter Jeremy J Starcher
  • Start date
J

Jeremy J Starcher

(Request for Discussion)

I've put together a guide that I hope will help novice coders avoid the
same hair pulling that I went through.

I'd like to thank all of you for your comments and suggestions.

I tried to give each one specific thought at attention. Although I
rejected a few ideas here and there that didn't fit with my desired goal,
they were still appreciated.

Following the Mantra of 'Release Early. Release often.' I offer my second
draft for discussion.

If your title bar does not indicate version 0.2, reload the page. Usually
the F5 key on most browsers, or the 'reload' button.

http://www.mopedepot.com/jjs/HowToRecognizeBadJavascriptCode.html
 
G

Gregor Kofler

John W. Kennedy meinte:

ACK. Well, as a non-native speaker I don't have the insights of JWK... I
have to rely on dictionaries.
That /is/ its English meaning -- its only English meaning until the
early 20th century when, as I said, some moron got the two words mixed
up. The fact that modern dictionaries perforce have to acknowledge the
mistake doesn't change that.

So what? Names, meanings, words have changed throughout centuries
because of errors in translation or simple typos. Being a percevtive
person, you've probably realised that the year is 2008. (You should move
to Iceland - their language hasn't changed over the last thousand years.
Well, at least only very slightly.)

Gregor
 
T

Thomas 'PointedEars' Lahn

Anthony said:
David Mark posted :

This is an excellent tip, thanks!

It's a recipe for disaster. Whenever you use scripts that use try..catch
as-is, compilation will fail with a SyntaxError. Compilation of the other
scripts, that you use along with them and that don't use try..catch, is not
guaranteed. It does not matter at all whether script A uses features that
are defined in script B, compilation is done in order of inclusion. Since
loading script resources dynamically is error-prone, the best thing you can
do for now is a) to avoid try...catch entirely or -- where that is not
possible or feasible, such as in XHR scripts -- b) to use eval to hide it,
what I proposed.
I've got my current XMLHttpRequest objects instantiating in try-catch
blocks.

And that is good so. However, it should be hidden as described.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Anthony said:
Jeremy J Starcher posted :

Additionally, the little-known CTRL-F5 that will defeat the cache (at
least in IE and FF)

Proper cache control headers are better than to rely on that feature.


PointedEars
 
L

Laurent vilday

Thomas 'PointedEars' Lahn a écrit :
If you do think that could do any good, you are using the wrong medium.
You are back out of my killfile, for now, but scored Lowest.

LOL, you are so funny.

Please, pretty please, don't answer me, just killfile me.

Oh yes please killfile me for ever !
 
A

Anthony Levensalor

Thomas 'PointedEars' Lahn posted :
It's a recipe for disaster. Whenever you use scripts that use try..catch
as-is, compilation will fail with a SyntaxError. Compilation of the other
scripts, that you use along with them and that don't use try..catch, is not
guaranteed. It does not matter at all whether script A uses features that
are defined in script B, compilation is done in order of inclusion. Since
loading script resources dynamically is error-prone, the best thing you can
do for now is a) to avoid try...catch entirely or -- where that is not
possible or feasible, such as in XHR scripts -- b) to use eval to hide it,
what I proposed.


I did some more reading after I posted that, actually, and I was
starting to come to that same line of thought, albeit not with any real
confidence. Thanks for the tip, I think I'll avoid them entirely for the
time being and use another method for making sure my code isn't going to
bomb.

As a Java developer, try/catch/throw/finally were staples of my
existence, and I naturally transitioned that. But, as has been said
many, many times here, Javascript is not Java. :)

~A!
 
A

Anthony Levensalor

Thomas 'PointedEars' Lahn posted :

Proper cache control headers are better than to rely on that feature.


Picky, picky.

Still a valid tip, however, just in case one should ever happen across a
page with, you know, improper cache control.

~A!
 
D

Dr J R Stockton

In comp.lang.javascript message said:
Is this a good use of eval?
function convertToDecimal(fraction){
return eval(fraction)
}

Where fraction is a fraction that you need converted to decimal? It can
be written like this:

function convertToDecimal(fraction){
var numerator = fraction.substring(0,fraction.lastIndexOf('/'))
var denominator = fraction.substring(fraction.lastIndexOf('/')+1)
return (numerator/denominator)
}
... or with .split("/") - but why last Index?


If that string is supplied from outside, then the case is already
covered as "not known at run time". Return.

Otherwise, no : it is not a good use of eval.

Evidently the argument 'fraction' is intended to be a string. But a
string is not a good way of representing a fraction internally. A
rational fraction should be represented as {Num:n; Den:d} or similar, or
as a case of {Typ:F; Num:n; Den:d}, or as a simple case of a structure
designed to hold general expressions (a tree for arithmetic notation; an
array or list for RPN).

It is only bad data design that makes the use of 'eval' seem appropriate
for that purpose.

It's a good idea to read the newsgroup c.l.j and its FAQ. See below.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
am.me.not.com>, Tue, 1 Jan 2008 13:50:01, Jeremy J Starcher
Once again, I don't know Thomas personally, but I will say this. This
group needs him and people like him. They are the ones who remind us of
the edge cases. They are the ones who will remember weird interactions of
code and will spot flaws long before they become an issue.

No. There are enough other people here with adequate knowledge for the
purpose combined with acceptable manners - even if one disregards those
who write at excessive length.

TL's particular defects include an urge to answer as much as possible as
soon as possible (he probably apologises for his own errors-in-haste
more than anyone else here needs to); and, when he does give an
incisive, correct, and comprehensible answer, the more normal experts
will feel no need to add their own incisive, correct, and believed
comprehensible version.

TL must have the effect of driving out, through his arrogant nastiness,
many who would otherwise he helped by this group.
 
T

Thomas 'PointedEars' Lahn

Jeremy said:
I'd like to thank all of you for your comments and suggestions.

You're welcome. However, appreciation in assistance of the improvement of
a publicly available resource is best done with mentioning the contributing
individuals therein. I suggest a summarized list on the bottom.
[...]
If your title bar does not indicate version 0.2, reload the page. Usually
the F5 key on most browsers, or the 'reload' button.
http://www.mnot.net/cache_docs/

http://www.mopedepot.com/jjs/HowToRecognizeBadJavascriptCode.html

1. Deprecated usage with script tag
^^^^^^^^^^
a. Still the wrong term here. Either "<script> tag" or "`script'
element". But something tells me it would still not be proper
English then. May someone who speaks English as native language
comment on this.

b. | <HTML3 introduced the <script> tag and the language attribute.>
| <HTML4, in turn, deprecated the language attribute in favor of
| the new type attribute.>

HTML 3.2, which is the current version of HTML3 and the only one
that ever achieved Recommendation status, introduced the `script'
element. The `language' attribute was _not_ defined for that element
before HTML 4.0 In fact, in HTML 3.2 the `script' element has no
attributes at all:

http://www.w3.org/TR/REC-html32-19970114#script

You are referring to an old working draft that says about itself:

| This is a W3C Working Draft for review by W3C members and
| other interested parties. It is a draft document and may
| be updated, replaced or obsoleted by other documents at
| any time. It is inappropriate to use W3C Working Drafts
| as reference material or to cite them as other than
| "work in progress". [...]

I also suggest not to make an entire sentence a link.

c. Again you used the term "depreciated" for "text/javascript".
But even "deprecated" would be inappropriate here; the MIME media type
was only marked _obsolete_ prematurely. "deprecated" is apparently
not a term available for the registration of media types, and
other terms were said to be rejected by the participants of the
corresponding Usenet discussion. (I was temporarily not
participating in Usenet at the time.)

2. Using "href:javascript"

should be changed into 'Using href="javascript:..."'.

The "better example" should be

<a href="myhouse.jpg"
onclick="showPicture(this.href); return false;"
Look! My house!</a>

which would demonstrate that graceful degradation does not imply
double maintenance.

3. Not declaring local variables (no var)

Assignment to an identifier that was not declared does not produce
a variable (a property of the Variable Object with the DontDelete
attribute), it adds/modifies a property of an object along the scope
chain, if that (it may as well throw an exception if that object
does not allow modification, such as in MSHTML). "The variable i
was not declared." does not make sense (that would be like "This red
cat is a blue dog."); "`i' was not declared a variable" would be
correct.

4. Use of eval

You forgot to mention the use of eval() to use necessary, but
not fully backwards-compatible syntax, such as try...catch.

5. Try/catch

w3schools.com should not be used as reference material (maybe Web
statistics aside if carefully evaluated). How it would deserve to be
linked as "the standard" is way beyond me.

6. Web pages that do not validate

a. The use of the word "page" for something that is seldom, if ever,
displayed on a page-wise medium is beyond me. Use `document'
instead.

b. "All web designers are strongly encouraged to use use a valid DOCTYPE"
does not make sense (the duplicate word aside). DOCTYPE is merely a
type of declaration in SGML. A valid DOCTYPE declaration does not
mean at all that the markup declared as such is Valid according to the
referenced DTD. "All web designers are strongly encouraged to create
Valid markup documents" would be appropriate. Mentioning of the
DOCTYPE _declaration_ as part of Valid markup should follow.


Unfortunately, your From and Message-ID headers still violate Internet
standard STD11/RFC2822, sections 6.2/3.4 and 4.6.1/3.6.4. Please fix that.


PointedEars
 
J

Jeremy J Starcher

You're welcome. However, appreciation in assistance of the improvement of
a publicly available resource is best done with mentioning the contributing
individuals therein. I suggest a summarized list on the bottom.

Ouch. Yes. Right on. I'll do that draft 3.
[...]
If your title bar does not indicate version 0.2, reload the page. Usually
the F5 key on most browsers, or the 'reload' button.
http://www.mnot.net/cache_docs/

http://www.mopedepot.com/jjs/HowToRecognizeBadJavascriptCode.html

1. Deprecated usage with script tag
^^^^^^^^^^
a. Still the wrong term here. Either "<script> tag" or "`script'
element". But something tells me it would still not be proper
English then. May someone who speaks English as native language
comment on this.

I changed that to element, then in a fit editing, must have changed it
back.

Ah.. thank you. I was trying to find that reference.
The "better example" should be

<a href="myhouse.jpg"
onclick="showPicture(this.href); return false;"

Spot on.
3. Not declaring local variables (no var)

Assignment to an identifier that was not declared does not produce a
variable (a property of the Variable Object with the DontDelete
attribute), it adds/modifies a property of an object along the scope
chain, if that (it may as well throw an exception if that object does
not allow modification, such as in MSHTML). "The variable i was not
declared." does not make sense (that would be like "This red cat is a
blue dog."); "`i' was not declared a variable" would be correct.

While true I am worried this might be too detailed. I'll give it more
thought.

5. Try/catch

w3schools.com should not be used as reference material (maybe Web
statistics aside if carefully evaluated). How it would deserve to be
linked as "the standard" is way beyond me.

I stand corrected.

b. "All web designers are strongly encouraged to use use a valid
DOCTYPE"
does not make sense (the duplicate word aside). DOCTYPE is merely
a type of declaration in SGML. A valid DOCTYPE declaration does
not mean at all that the markup declared as such is Valid
according to the referenced DTD. "All web designers are strongly
encouraged to create Valid markup documents" would be appropriate.
Mentioning of the DOCTYPE _declaration_ as part of Valid markup
should follow.

I see your point there.
Unfortunately, your From and Message-ID headers still violate Internet
standard STD11/RFC2822, sections 6.2/3.4 and 4.6.1/3.6.4. Please fix
that.

Should be fixed now. I think.
 
T

Thomas 'PointedEars' Lahn

Randy said:
Thomas 'PointedEars' Lahn said the following on 1/2/2008 9:13 AM:

And an even better solution would be:

<a href="myhouse.jpg"
onclick="return showPicture(this.href)"

It was a better solution where a popup window was involved. But it would
require an additional explanation of the return value of showPicture(),
which is why I did not propose it.
While ignoring the missing - mandatory - attributes.

There are no required attributes missing here.


PointedEars
 
R

Richard Cornford

Anthony said:
Thomas 'PointedEars' Lahn posted :

Maybe not guaranteed but it has generally been observed that a syntax
error in the contents of one script element (or in a resource imported
by a single script element) does not interfere with the successful
interpretation/compilation of syntax error free code in other script
elements (or imported by other script elements) within the same
document. Any cited examples where it did would be important, but in
their absence this seems excessively paranoid.

If there is no guarantee that a syntax error at any point will not have
a negative impact outside of the particular interpretation/compilation
process (or, given that there is no guarantee, this is being assumed to
be a pertinent issue) then eval-ing potential syntax erroring code could
only be employed once per document as there must be no guarantee of the
ongoing consequences in the event of the syntax error actually occurring
when tried.
I did some more reading after I posted that, actually, and
I was starting to come to that same line of thought, albeit
not with any real confidence. Thanks for the tip, I think
I'll avoid them entirely for the time being and use another
method for making sure my code isn't going to bomb.

As a Java developer, try/catch/throw/finally were staples
of my existence, and I naturally transitioned that. But,
as has been said many, many times here, Javascript is
not Java. :)

Go back 4-5 years in the archives and the general advice would have been
never to use try-catch outside of the known/controlled environment of an
intranet. But there eventually does come a point when newly introduced
features start to seem viable in the general web context.
Try/catch/finally have been part of the language specification since the
turn of the centaury (more than half of the total existence of
javascript) and it is extremely unlikely that any new JS engines will be
created without some form of sensible handling for the construct. So any
residual compatibility issue is really just in relation to very old web
browsers; mostly the forth generation of browsers and their antecedents.

(However, note that it has been suggested that IE 5 supported this
construct, but in reality JScript 5.0 did not include any support for -
finally -, and is very slightly off-standard in its support for
try-catch (though not in a way that would be problematic in normal
situations).)

On the other hand, javascript's try/catch construct is nearly totally
useless (non-practical) for various reasons. The first of which is the
way in which it must be used.

In Java (and other languages with good exception handling support) you
can be very specific about which exceptions you catch and handle (and so
will be letting any exception that cannot be handled propagate). While
in javascript you have no choice but catch every exception that is
thrown. That means that having caught your exception you then have to
work out if it was the exception you were planning to handle and if not
re-throw it.

That then introduces the second problem with javascript's try/catch,
which is identifying exceptions. There are some things that the
language's specification does allow you to determine from an - Error -
object, and in some cases that will include the necessary information
needed to identify the Error. One of (or a combination of) the Error's -
constructor - or - name - properties should allow for the identification
of the type of Error object, at least for the exceptions thrown as a
direct result of correct implementation of the language's specified
algorithms (which might broadly be categorised as "NativeErrors"). The
problem is that knowing that a caught exception is, for example, an
instance of "ReferenceError" does not really pin down which error it is
you are handling (unless the code in the - try - block is so restricted
that there is only one point where a "ReferenceError" could be thrown.

This comes to the question of the Error's - message - property. In
reality messages are usually fairly explicit about what exception has
been thrown (and often where), but not in any standardised way. The
specification for the message property says "The initial value of
Error.prototype.message is an implementation-defined string" and never
gets more specific than that. And as a result no two browsers can be
expected to produce the same message in association with the same
exception. Indeed, any single browser with a language configuration
option may not produce the same message given two differing language
configurations (they are, after all, messages to the programmer and
might reasonable be presented in the programmer's specified (possibly
native) language given a script engine author with an appreciation of
the role of language in human culture).

And if the specified - message - property is not going to help identify
individual Error objects then any implementation specific 'errorNumber',
'description', or other non-specified properties of the Error object are
going to be of even less use.

That is all just with language specified exceptions and the resulting
Error objects. Next we have the browser and the DOM both being likely to
throw exceptions in response to executing javascript code. The W3C DOM
defines a DOMException interface with a - code - property that could be
used to identify the type of an exception thrown by the DOM. Except that
in reality DOM implementations throw other exceptions, such as some
Opera 7 versions throwing a "NOT IMPLEMENTED" error when a particular
method was called (which the DOM specification asserted should not throw
an exception at all when called), and the W3C DOM specifications provide
no code number for "NOT IMPLEMENTED" (indeed they could not as the DOM
modules, as specified, are an 'all or nothing' game, regardless of the
reality of many browsers having 'good enough' but incomplete
implementations).

But then there is the browser itself, which can throw any exception it
likes ("out of memory", "too much recursion", "permission denied") and
no matter how many 'name', 'message', 'description', 'type' or 'number'
properties such Error objects may have you are going to have a hard time
identifying any of those. At best you would be looking at a trial and
error process of provoking possible exceptions in known browsers and
recoding their 'unique' characteristics and then writing code that test
for them. A process that is as incompliable as attempting to create a
comprehensive browser sniffing system based upon object inference.

So javascript's try/catch implies the need to catch all exceptions and
then identify the exception caught to see if it is an expectation that
can be handled, and re-throw those that cannot be handled. But the
ability to identify exceptions is so limited/problematic that you would
be hard pressed to find any single example of anyone actually coding
this. And indeed the mass of code that would then necessarily appear in
every - catch - block would be so obviously excessive as to tip anyone
off that any genuine exception handling in javascript was a nightmare to
attempt.

As a result what you usually see are empty (or pointless: 'alert('Some
sort of script coded f**k-up that you, as a user, can do nothing
sensible about has happened');') - catch - blocks, sometimes (but by no
means always) followed by some code to test for the consequences of the
caught and suppressed exception having been thrown (such as checking to
see an expected XML HTTP request object does exist after the attempt to
create it).

This style of try/catch use can be practical but its sensible
applications are very few and far between. Indeed it is characterised by
your usually only seeing a single statement being executed inside the -
try - block so the potential expectations thrown at that point are
extremely limited in range. So obviously any attempt to apply such a
style on a larger scale would virtually have every statement inside its
own - try - block, and result in the inverse of the nightmare of trying
to identify exceptions in order to handle them.

Thus, one web application I work on has well in excess of 100,000
statements in its client side code, is designed for use where the
browser(s) is(are) specified and so support try/catch/finally, yet in
all of that there are just 4 tiny try/catch blocks. A general strategy
of defensive programming, where potential exception throwing conditions
are test for up-front and so never provoked is the best strategy for
avoiding all of the issues with try/catch. Of course that is probably
easier to implement for those of us who were doing this 4-5 years ago
when any use of try-catch on the public Internet was pretty much out of
the question.

For completeness, there is still potential for using try/catch in
javascript, and particularly when designing large/complex systems (which
maybe is not such a good idea with javascript as a language to start
with, but anyway ...). It would be reasonable to design a system that
made heavy use of its own exceptions, while pretty much ignoring any
other exceptions. If you are creating and throwing your own custom
exceptions you can guarantee that those expectations do carry enough
information to allow for their easy identification, and so allow for the
sensible handling of those exceptions (but only those exceptions) when
they are thrown. I have never had a desire to do that myself, but if a
system was designed from day one to use such an internal exception
handling system it could be completely justified, effective and reliable
(and certainly in a browser restricted context).

Finally, there definitely is a down side to showing the use of try/catch
to novices in that they sometimes latch onto them as a universal
panacea, wrap everything they write in try/catch blocks and so suppress
all errors. This leaves their code 'error free', in one sense (the sense
of showing errors to the user) but it results in code that is virtually
impossible to maintain because if it is ever observed to be 'not
working' (which is not at all unexpected under the circumstances) then
it is virtually impossible to work out why.

So any discussion of indictors of bad code can validly mention the use
of try/catch because many specific patterns in its use are very
indicative of bad code.

Richard.
 
A

Anthony Levensalor

Richard Cornford said:

So any discussion of indictors of bad code can validly mention the use
of try/catch because many specific patterns in its use are very
indicative of bad code.

I just want you to know I read the whole thing. Thanks for the
informative post.

~A!
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
am.me.not.com>, Tue, 1 Jan 2008 20:26:47, Jeremy J Starcher
By design. I don't have a personal home page nor do I have a computer
related page anywhere. The page is hosted on a work server with
permission.

H'mmm - perhaps there should be a standard icon, looking in part like a
broken link, for "Homeless"; it would stop people continuing to look for
a Home link. But, if you add any pages, you could call that one Home.

With a "rule of thumb" it is much harder to define "right." In practice
I strongly discourage use of document.write. In practice, I use it
sparingly.

You may have missed the chemical point.

I will Google for that later. Do you have a licence template that you
recommend?

No. But you can see what my Home Page says. You might find it better
to say nothing more than the standard copyright reminder.
 
D

Dr J R Stockton

In comp.lang.javascript message <8331b1ee-5f11-4391-bdc6-05d427912e5f@e2
6g2000hsh.googlegroups.com>, Tue, 1 Jan 2008 16:35:16, David Mark
Another reason to minify is
that compression (when available) will only reduce comment bulk,
whereas minification eliminates it.

ISTM wrong always to use something that eliminates all comment, even on
a fully-commercial page not intended to be read. Comment explaining the
code should be removed; but comment identifying the source and date can
be worth retaining.

Perhaps the language should be extended with a convention that comment
to end of line which starts ////, and/or other comment which starts /**
(and finishes **/ ?) should be retained by minification.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>, Wed,
2 Jan 2008 15:13:24 said:
Unfortunately, your From and Message-ID headers still violate Internet
standard STD11/RFC2822, sections 6.2/3.4 and 4.6.1/3.6.4. Please fix that.

Have you considered consulting a good craniotomist?
 
D

David Mark

It's a recipe for disaster.  Whenever you use scripts that use try..catch
as-is, compilation will fail with a SyntaxError.  Compilation of the other
scripts, that you use along with them and that don't use try..catch, is not
guaranteed.  It does not matter at all whether script A uses features that

That is outrageous nonsense. The script(s) with try-catch will not
parse. Other scripts in the page that do not use try-catch will be
fine as long as they do not rely on the ones that do. If you wish to
be overly paranoid about it (which you apparently do), you can order
the try-catch scripts last.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,330
Latest member
AlvaStingl

Latest Threads

Top