
JavaScript pattern and antipattern collection - mshafrir
http://shichuan.github.com/javascript-patterns/
======
StefanKarpinski
You know what's an antipattern? Putting a fixed floating div _over_ the text
you're supposed to be reading so that you can't read it. Brilliant.

~~~
alextgordon
Expand that to "Sites which don't work unless your browser window is
maximised". It's astonishing how many web devs think that just because
"nobody" has 1024x768 screens, they can assume that nobody has 1024x768
browser windows.

For example, visit <http://campfirenow.com/>, make your browser window
skinner, scroll to the bottom/top right, and observe how the page craps
itself.

Or how about <http://jobs.37signals.com/>. Make the browser window thinner,
scroll to the righ- oh right you can't because _they disabled horizontal
scrolling_.

I don't mean to pick on 37signals. They're not alone. Web people: make your
browser window smaller and, you know, make sure your site still functions.

------
romaniv
This is a great example of why I dislike JS as a language. There is a page on
optimizing for loops with _6 examples_. Four of them are deemed sub-optimal.
The two "preferred" examples are miles away from being intuitive or natural.
And it's not an exception.

There are just way too many ways to do things wrong.

~~~
grannyg00se
The only significantly sub-optimal example is the first one, which is labeled
as such. And it isn't particularly unintuitive that computing the upper bound
of the loop on each iteration is going to slow down the computation.

Also, none of the methods are actually wrong. These are code optimizations.
You can find tricky little code optimizations in any language. And in compiled
languages you also have compiler optimizations that you can apply if you
really need to squeeze out more performance. It's not fair to say that it's a
pitfall of the language that this is possible.

Some better examples of javascript having unintuitive pitfalls would involve
things like triple equals, for...in and hasOwnProperty, or semi-colon
insertion, or function scope (as opposed to block scope) or .... well there
are a lot. But most of the time the reason they are unintuitive is because the
intuition we are relying on comes from other languages. They are not
javascript. If you take the time to actually learn javascript as its own
language it turns out to be a pretty decent language to work with.

~~~
Chris_Newton
_And it isn't particularly unintuitive that computing the upper bound of the
loop on each iteration is going to slow down the computation.

Also, none of the methods are actually wrong. These are code optimizations._

That may be true, but the optimization you're talking about is only necessary
if:

(a) a language's semantics aren't expressive enough to guarantee that the
length of the array won't change in mid-iteration, and

(b) the language's runtime environment can't optimize away the repeated look-
up on the fly, having determined that nothing within the loop actually is
updating the length of the array even if such a change is permitted by the
rules of the language.

Both of these things are properties of JavaScript, or at least the particular
implementation(s) of JavaScript where the optimization is required.

While this sort of detail isn't an absurdly bad idea in the way that, say,
semicolon insertion turned out to be, I don't think it's reasonable to say
they are somehow not negative points for JavaScript. Many other languages can
and do handle similar situations in better ways.

~~~
grannyg00se
First, let me throw in the obligatory "don't optimize prematurely" suggestion
here. I think it probably fits well in this for loop "optimization"
discussion.

As for your points a and b, I believe some implementations (V8 comes to mind)
actually do handle this optimization for you indicating that the language
isn't preventing it.

People are free to come up with a better js runtime, just as people are free
to come up with their own compilers for other languages. You're going to get
some variation depending on what language constructs you use with a particular
compiler and its compile-time settings.

"Both of these things are properties of JavaScript, or at least the particular
implementation(s) of JavaScript where the optimization is required."

So if I build a particular implementation and you run your code on it and find
your code running horribly, you'll blame javascript?

~~~
romaniv
_As for your points a and b, I believe some implementations (V8 comes to mind)
actually do handle this optimization for you indicating that the language
isn't preventing it._

The language isn't mandating it either. Therefore, anyone working with the
language will be forced to deal with multiple obscure optimizations _and_ with
different language implementations.

Loops are just one example. JS is choke-full of similar issues.

~~~
Chris_Newton
Exactly. Optimisations like this are a least common denominator problem, in
that to some extent you have to cater for the worst runtime that your code is
likely to run on, even if other runtimes would do a better job without needing
your help.

As for the premature optimisation comment made by grannyg00se above, I am very
wary of applying that logic here. We're talking about an _obvious_ potential
inefficiency that is _actively_ being introduced if we choose to write a for-
loop in a certain way that most of us are used to. As the original article
demonstrates, there are many other ways we could write that loop without that
inefficiency, so I think this is more a case of not introducing unnecessary
overhead when there's no good reason for it. (We don't _know_ it's going to be
an inefficiency in practice, but assuming it won't be is essentially a
Sufficiently Smart Compiler argument.)

------
greggman
Everyone has their own style. As one controversial example, some programmers
do this

    
    
        if (condition)
          singleStatement;
    

Their POV is less lines = better.

And others do this

    
    
        if (condition) {
          singleStatement;
        }
    

Their POV is defensive programming and or consistency is better.

Similarly, some programmers prefer

    
    
        var a, 
            b, 
            c = 3;
    

Because less typing = better. Others prefer

    
    
        var a;
        var b;
        var c = 3;
    

Because they prefer consistency and defensiveness. Deleting any line doesn't
effect the others where as in the 1st example, delete the first or the last
line and other lines have to change (which is funny since that means MORE
typing).

Yet another example

    
    
        if (condition) {
          statement;
          statement;
        }
    

vs

    
    
        if (condition) 
        {
          statement;
          statement;
        }
    

Some prefer the first because it's shorter. Others prefer the second because
it's consistent and keeps the blocks separate and movable.

IMO one vs the other is not a pattern vs anti-pattern. It's a style decision.
Me, I'm on the consistency and defensive programming > shortness of typing
side of this fence. It's disheartening to see some self appointed JS gurus
claim their 'style' is better when clearly it's just 'style'.

~~~
tszming
Because of the implicit semicolon insertion in JavaScript, it is better to
place the curly brace next to the condition IMHO.

After all, I agree the most important thing is to be consistent.

------
sixcorners
We have to name javascript functions twice?

We should be using eval to get the global object?

If you are going to go through that hassle to get the global object why not do
the same for everything else you will ever use? Every single external variable
could have it's own privately named identifier. Won't that be fun.

~~~
Jach
At first I thought the naming-twice thing (which I've never done or seen) was
similar to the C idiom of doubly naming your typedef structs so users don't
have to type `struct Foo` everywhere if they don't want to. I was envisioning
a useful application with Node where you might say `exports.foo = function
foo() { };` so you can call `foo();` instead of `exports.foo();` in the same
code file, but that doesn't seem to work when I tried it and so this "pattern"
is useless in that context. (Meaning I'm back to `function foo() { }` and then
`exports.foo = foo;`.)

~~~
dspeyer
exports.foo = function foo() { }; is indeed where you might use this. It
doesn't let you call it as foo(), though. What it does is make
exports.foo.toString() include "foo". This can be useful for debugging, and
possibly other things.

------
geuis
Could you make it so the sidebar doesn't cover 40% of the screen and thus most
of the content?

~~~
tomg
$('#toc').removeClass('sticky');

I keed, I keed...

Sidenote: A bunch of the code samples I checked out are ripped bit for bit
from "JavaScript Patterns" by Stefanov (O'Reilly/Yahoo! Press). I recommend
that book to any JS dev along with the famous "Javascript: The Good Parts".

------
omgtehlion
some of these “antipatterns” are just stupidities. and a little number of
“good practices” in this list actually have a lot of downsides, rendering them
antipatterns.

and the sidebar is really annoying.

------
iamleppert
I've never understood:

if(typeof document.attachEvent !== undefined) document.attachEvent(...)

wouldn't if(typeof document.attachEvent == 'function') be much better?

that way you assure it's actually something that's actually callable?

~~~
ufo
To be fair, if attachEvent exists and is not a functions then some deep shit
must be going on. In the first case you at least get an error to tell you
about it.

But in general I prefer to use `'prop' in obj` instead of testing `obj.prop`
for undefined. Some methods in IE browser objects have funky getters that
sometime throw exceptions if you try to read them so using `in` is safer.

------
ww520
One man's anti-pattern is another man's normal coding. Just don't be dogmatic
about it.

