
JavaScript Garden - aundumla
http://bonsaiden.github.com/JavaScript-Garden/
======
tkiley
Excellent write-up! I've learned most of these things the hard way :/ I'm
filing this away to recommend to any developers who are setting out to use
Javascript extensively for the first time.

One quibble: In the "common pitfalls" section regarding the "this" object,
they say that locally-defined functions within other functions _never_ have
any practical use. I might disagree: with a little coaxing, you can convince
locally variables inside the constructor (both functions and other variables)
to serve as private properties of an object; this is the only technique I know
that allows for private properties.

(I haven't actually done this in code that has been maintained/used anywhere,
I just did it as an experiment and filed it away as a "that's cool" for future
reference)

Edit: Here is an example of what I'm talking about:
<https://gist.github.com/866103>

~~~
csomar
Be careful of that. There is a trap right there. Your example is using the
"new" keyword and not executing the function. So what happened?

1\. If you use the "new" keyword, and don't execute the function. "x = new
foo()". X becomes an "object". "foo()" is behaving like a _class_. You got to
define the properties and methods of this class with the "this" keyword. Once
you create your object with the "new" keyword, these variables got assigned to
the object. And better, you can access them with the prototype.

2\. If you execute the function in your code, that is you put "foo()": Open
your FireFox with FireBug and notice two new global variables in the Windows
object "get_my_private" and "set_my_private".

So it depends on the usage. "this" insides of a function is useful, if your
intent is to use the function as a class. If not, it's dangerous, as the
variables becomes global and may interfere with other variables.

~~~
Groxx
There's an easy way to fix that, though:

    
    
      function Foo(){
        if (this == window) throw "USE NEW!";
        // continue with object creation
      }
    

Or use the standard practice of having class-creating function names
capitalized, and let people know to follow it.

------
csomar
Does anyone have an idea of what happened to "The secrets of the JavaScript
ninja"? I'm impatiently waiting for this book to be released.

~~~
halostatue
It's in review (I'm an occasional Manning reviewer and have looked at this
recently).

~~~
csomar
Can we know, when this is going to be released? Not looking for a precise
date, just a range.

~~~
senko
There's some info about the status and estimated publishing date at
<http://www.manning.com/resig/>

------
mrspeaker
This looks like an excellent resource for when you are too lazy to get up out
of your chair and pick up your copy of "JavaScript: The Good Parts" ;)

~~~
Tomek_
It's a great book but one has to note that not everything there is "how things
should be done" these days, Crockford himself has changed his mind on some of
the things he wrote there. Take this as for example:
<http://www.bolinfest.com/javascript/inheritance.php> or that the book
advocates extending native objects (including "Object").

------
andreyf
In the prototype example [1], could someone explain the point or at least the
effect of setting Bar.prototype.constructor = Bar?

1\. <http://bonsaiden.github.com/JavaScript-Garden/#prototype>

~~~
nfriedly
A couple of lines up you see this:

    
    
      Bar.prototype = new Foo();
    

Then, Bar.prototype.constructor == Foo()

So when you create a new instance of Bar, it's constructor still appears to be
Foo even though it really isn't. Setting the prototype.constructor fixes that.

------
senorpedro
similar: <http://wtfjs.com/>

------
extension
_the native prototypes should never be extended unless it is for the sake of
compatibility with newer JavaScript features_

A bit controversial, don't you think?

~~~
netghost
I think it's more of an issue of who is doing the extending. If it's your own
code in a non shared library, then it's up to you.

If it's in a shared library, it is probably nicer to avoid. For instance, if
you override a function on a native prototype, you might be overwriting some
future function that browsers will implement. I've seen this done with
Array.map for instance.

~~~
amadeus
Well that's why the statement is controversial. This person flat out says,
NEVER extend native prototypes except for 1 single case.

Sorry, but blanket statements like that are complete B.S. It all depends on
context; it makes me dubious of the rest of this article if they can get away
with statements like this.

~~~
wvenable
With JavaScript, it's still _extremely_ good practice -- you don't know what
code you might break by extending the native prototypes. You may make it hard
to integrate your code with libraries or other code.

It's really not _that_ controversial.

~~~
amadeus
Actually, that's still the point though. If you are building a library to be
used in a variety of contexts, with no prior knowledge of the environment,
it's probably not a good idea to extend native prototypes.

If however, you are building a site or web app (like the majority of
Javascript developers, I would assume), then the benefits of extending
prototypes within your app can provide great advantages and keep your code
much cleaner.

So again, I am not saying don't extend, and I am not saying extend, I am
simply saying, that I agree that one should err on the side of caution and
asses the situation for which they are coding for and make a decision
regarding those circumstances. Simply saying a best practice is to 'never' do
it to me is quite short sighted and is not properly educating new developers
on how to write good Javascript.

For the record, I have often extended natives within my applications, and have
never once had a conflict.

~~~
wvenable
> then the benefits of extending prototypes within your app can provide great
> advantages and keep your code much cleaner.

The assumption here is that you're never going to use any 3rd party code.
Sure, a lot of libraries are forgiving of extended natives, but certainly not
all JavaScript code is (especially code written before the hasOwnProperty
method existed).

> For the record, I have often extended natives within my applications, and
> have never once had a conflict.

I have as well, it seems like a much more common practice in the past than
now. I did, however, have conflicts with code (a date popup script, for
example) that also extended natives. Now neither my own code, nor later
versions of that exact script, extend natives anymore. I don't think the
advantages are really all that great to warrant messing with them.

~~~
amadeus
You're actually further proving my point. I said that if you are writing an
external library, it's a good practice NOT to extend prototypes since the
context the plugin will be used in is entirely unknown.

The argument that you are giving for internal application development is akin
to saying, well shit, someone could set your global namespace to null, so now
what? Stop namespacing?

The better solution is don't use a crappy plugin. I prefer to write clean,
maintainable, easy to read code with great abstractions, which would mean I
refuse to use a shitty library and would opt instead to rewrite it myself or
find a new one that does it right.

Again, I really don't see this as an issue, because extending native
prototypes is one of Javascript's more powerful utilities.

------
Kilimanjaro
Everyday you learn something new

    
    
      Number.prototype.times=function(fn){
        for(i=0;i<this;i++){ fn(i); }
      }
    
      3..times(alert)

~~~
zoul
If somebody’s wondering about the double dot like me: “A common misconception
is that number literals cannot be used as objects. That is because a flaw in
JavaScript’s parser tries to parse the dot notation on a number as a floating
point literal.”

------
btipling
Should probably also mention the Function constructor in the eval section.
Also object keys are always are type cast into strings so object[1] = "moo"
becomes object["1"], this is rarely a problem but can be.

------
ck2
Very well done.

I'd add under _setTimeout and setInterval_ that anything below _8ms_ may not
work as expected across different browsers/hardware. Even setting _1ms_ to
indicate "as soon as possible" may not occur as expected when repeatedly
called.

also: the font size is a little small for my eyes in the code boxes - I can
fix it of course with stylish but maybe that can be addressed directly on the
site

~~~
BonsaiDen
We have a newer version of the website in the works, but it's getting delayed
to my new job. I hardly have anytime at the moment to work with Yi Jiang on
the style since I spend 5 hours a day sitting in a train. But that will change
as soon as I manage to move.

------
tomelders
I've seen so many people insist that Javascript code should be Semicolon free
recently. It always felt wrong to me, mainly because I code in several
languages and getting into the habit of not using semicolons felt dangerous.
It's nice to know there's a genuine reason to continue using them.

------
roryokane
This site is too light on details for me to trust its conclusions.

Under “The evil eval”, it concludes that you should never use eval simply
because it sometimes executes in global scope. That does not seem like an
obvious conclusion to me. Yes, it’s a mistake to use it on user input, but
that is easily avoided. I think the site should give an example of a situation
where you think you need eval, the problems eval _necessarily_ brings in that
case, and how to write that without eval. Otherwise, I don’t trust that the
site writer has actually explored why people use eval or what eval might be
able to provide that nothing else can.

Also, under “Automatic semicolon insertion”, the site does not mention the
alternative to using semicolons everywhere, which is not using semicolons but
remembering to put a semicolon before each line starting with parentheses.
That is a valid alternate practice, and the site ignores the possibility
without even discussing its problems.

The fact that each of those two sections contain grammar mistakes (comma
splices) also signals a lack of attention to detail.

~~~
roryokane
Why the downvote? I thought I gave ample justification for my criticisms of
the article, and my criticisms were constructive.

------
alexyim
One gotcha I've noticed a lot is when people forget to check for Console
object. Or they might do this (doesn't work):

    
    
      if(!console)
    

instead of

    
    
      if(!window.console) or if( typeof console === 'undefined' )

~~~
amadeus
I have to plug my console wrapper which takes care of problems like these :)

<https://github.com/amadeus/dbg>

------
koraybalci
great design (in addition to the content). How did you make it? I like the
right contents column changing topic as I read.

~~~
pistoriusp
The position of the articles are stored in an array when the dom is loaded.

When the document scrolls it compares the scroll position to the stored offset
positions.

If an article is close enough to the scroll offset it's highlighted.

------
hanifvirani
Looks helpful and is neatly presented. It would be great to have something
like this replicated for other languages.

------
sawyer
Love it; I'll definitely switch to strict equality comparisons from now on!

------
Ruudjah
Well written, clear syntax highlighted examples. Upboat.

------
kifou1
Thanks for the tips, very intresting

------
simpsond
Very good job.

------
wkasel
Very useful.

