Javascript Users Group
Travelers • Scott Sauyet • February 28, 2012
Javascript Users Group
======================
### Scott Sauyet ###
### February 28, 2012 ###
Agenda
======
... Nahhh
Reasons for a Users Group
=========================
* Peers
* Learning
* Sharing
What Is JavaScript?
===================
* The scripting language of the Web.
* Created by Brendan Eich of Netscape.
* Copied (warts and all) by Microsoft for Internet Explorer, by Opera, and by
others.
* Standardized by European Computer Manufacturer's Association, and officially
known as ECMAScript.
* Now on the 5th edition of the ECMA-262 standard, since December 2009. Most
browsers are still on the 3rd edition.
Other Environments
==================
JavaScript can run in other environments than the browser.
* [Rhino] for Java applications.
* [JScript.NET] for .NET applications
* [Apple Dashboard Widgets], [Microsoft Gadgets].
* Plug-in environments for many tools, such as [Yahoo! Messenger].
* Flash/Flex. Actionscript is just an ECMAScript dialect.
* [Server-side environments], most recently [Node].
General Javascript References
=============================
The set of references for JavaScript is spotty at best.
* Books: there are only a few general-purpose JavaScript books worth reading.
* Online References: Mozilla's reference pages are thorough and useful, but
difficult to navigate and very slow to load. (This seems to be changing.)
Microsoft's are hard to find and often incomplete or incorrect.
These are still important sources.
* Online Tutorials: Mostly a waste of time.
* Library References: There are some pretty well documented libraries. And
many that aren't.
JavaScript Books
================
* _[Javascript: The Definitive Guide]_, by David Flanagan. This is the best
accessible description of the language available.
* _[JavaScript: The Good Parts]_ by Douglas Crockford. This short book
discusses what JavaScript got right, and what should be skipped. It's
opinionated and thoughtful, and a quick read.
* _[Eloquent Javascript]_, by Marijn Haverbeke. This is a great introductory
tutorial.
-----
* _[JavaScript Patterns]_, by Stoyan Stefanov.
* _[High Performance JavaScript]_, by Nicholas Zakas
* _[Test-Driven JavaScript Developement]_, by Christian Johansen
Online References
=================
* The [Mozilla Developer Center] has lots of good information, and much of it
is relevant to most browsers. It has historically been slow to load, and
sometimes difficult to navigate, but the information is quite useful,
especially concerning the APIs.
* Microsoft's [JScript documentation] is less complete, less useful, and equally
hard to navigate, but is the only source for certain information related to
Internet Explorer.
* [Wikipedia](http://en.wikipedia.org/wiki/JavaScript) has mostly correct
and sometimes complete information on JavaScript.
* Peter-Paul Koch maintains the best list of browser compatibility information
at [Quirksmode].
Online Tutorials
================
* Recommended
- [Brown University CS Department Tutorial] is old and very basic, but
correct and good for beginners.
- [Essential JavaScript] by Patrick Hunlock is a pretty good overview of the
language.
* Not recommended
- [About.com: Javascript] is out of date and filled with misinformation.
- [w3Schools.com] seems to be about ten years out of date.
- Almost everything else. (There are certainly other good ones out there, but
they are hard to find.)
Other Resources
===============
* [Crockford's Videos] on Yahoo! Video teach many levels of JavaScript. He is
not only knowledgeable, but also a very good instructor.
* The [ECMAScript Specification] (or [Version 3] [ECMAScript Specification 3])
is not for the faint-hearted, but it does get you all the gory detail you'll
ever want.
* Mailing Lists and News Groups: A mixed bag, but the best bet to learn more
advanced techniques. [comp.lang.javascript] is the best-known of them. It is populated with many pedantic,
obnoxious personalities. However these are often the most knowledgeable people in the forum.
[jsmentors] is less volume, much less spam, and often more helpful, but some of the best minds around
don't participate
What JavaScript Has to Do With Java
===================================
* **Nothing!** It was just a marketing ploy between Sun and Netscape.
* JavaScript can be used to script Java applets, but it can equally well script
other plug-ins, such as Flash or PDF.
* It does share superficial syntactic similarities with Java. This is
legitimate in either language:
> for (i = 0; i < myArray.length; i++) {
> if (i % 3 == 0) {
> doSomething(myArray[i]);
> } else {
> myArray[i] = i * myArray[i];
> }
> } // end loop
* It of course is quite familiar to C, C++, and C# developers.
JavaScript Features
===================
* Dynamic Typing
* First-class functions
* Inheritance through prototypes
* Compact, readable literal formats
* Surprisingly quick (in modern implementations)
Libraries
=========
There are numerous JavaScript libraries available to help with specific tasks.
A small number of them are of reasonably good quality. Most are awful. There
are also general-purpose libraries meant to help with large parts of building
your JavaScript application. The best-known of these are:
* Prototype/Script.aculo.us
* Dojo
* YUI (Yahoo User Interface)
* Ext
* MooTools
* jQuery
Prototype/Script.aculo.us
=========================
Prototype is the great-grandadddy of modern JS Libraries. It was created as
part of Rails, and is much inspired by Ruby.
> $('comments').addClassName('active').show()
Heavy on modifying the prototypes of built-in objects.
Script.aculo.us is a add-on that adds animations, effects, drag-and-drop, and
some additional functionality. This keeps the Prototype core relatively small.
Prototype seems to be falling out of favor. It's not being updated as much and
mindshare seems to be moving toward jQuery.
Dojo Toolkit
============
Dojo has also been around for years. It never really makes clear what its
defining features are supposed to be.
> dojo.style("basicFadeNode", "opacity", "0");
> dojo.fadeIn({node: "basicFadeNode"}).play();
This was originally an IBM-led consortium attempting to collect general
best-practices, and some of that shows in its fairly jumbled API.
If this hadn't already gotten a foothold in a number of large corporations, it
could officially be called dead. But there are always people working on it.
YUI
===
Designed for building rich interactive applications on the web. It focuses more
than the previous two on widgets and highly visible DOM changes.
> YUI().use('anim-base', function(Y) {
> var anim = new Y.Anim({
> node: '#demo',
> to: { opacity: 0 }
> });
> anim.run();
> });
There are many complaints about YUI being bloated and very slow to download but
it is generally responsive and useful once downloaded.
Ext
===
Ext is a widget library. Any other features are secondary. It is by far the
snazziest widget library available, and probably the best documented as well.
It depends on a pluggable core, and can be used on top of its own core or
Prototype, jQuery, or YUI.
> var win = new Ext.Window({
> id : 'myWindow',
> title : 'My first Ext JS Window',
> width : 300, height : 150, layout : 'fit',
> autoLoad : {
> url : 'sayHi.html',
> scripts : true
> }
> });
> win.show();
MooTools
========
MooTools is all about object-orientation. It is considered by its proponents
as an abstraction layer between the browser and your code. It tries to smooth
over the differences between the browsers and enhance them by adding to the
core objects and adding utility objects.
> window.addEvent('domready', function(){
> new SimpleImageSlideShowDemo({
> imgUrls: [
> "slide1.jpg",
> "slide2.jpeg",
> "slide3.jpeg",
> ],
> container: $('imgContainer')
> });
> });
JQuery
======
"Find something; do something." The jQuery mantra is simple. jQuery is
focused on easily selecting the DOM items you want and performing simple
operations on them. It's keeps a fairly small core but has a powerful and
easy-to-use plug-in mechanism.
> $("tr:nth-child(odd)").addClass("odd");
jQuery is perhaps the easiest library to learn. It also has a strong evangelism
team. These have helped make it the recent king of the libraries. This is fine
with me as it's my favorite among them.
We'll examine more deeply how to use it, but first a little about its flaws.
JQuery Issues
=============
* jQuery makes it perhaps **too** easy to simply find some elements and add
handlers to them. This ignores the benefits that could be gained from
event delegation.
* jQuery's general API is relatively easy to remember, but the main function,
`jQuery` (aka `$`), is terribly overloaded. It can be used to
- create a wrapped collection of elements from a selector, a DOM element, an
array of DOM elements, another wrapped collection, or the clear blue sky
- build a new wrapped HTML element from a string, or build one and set
properties and run functions on it.
- run a callback function once the DOM is ready
* Its attribute handling is a convoluted mess that might or might not do what
you need.
Using JQuery
============
Example: To zebra-stripe all tables on the page using CSS class "odd":
> $("tr:nth-child(odd)").addClass("odd");
To do this only on tables that have the class "zebra"
> $("table.zebra tr:nth-child(odd)").addClass("odd");
Example: To add a hover class to rows when the mouse is over them:
> $("tr").hover(function() {
> $(this).addClass("hover");
> , function() {
> $(this).removeClass("hover");
> });
JQuery Notes
============
* `$` is just an alias to the `jQuery` main function. These are the only
global variables exposed by jQuery.
* At the heart of jQuery is its CSS selector engine. It's quite easy to
find elements you care about, using CSS and some extensions to CSS.
* The jQuery object that's created is a wrapper around a number of DOM elements
and most methods work on them as a group. You don't need to check the size
of the collection or iterate over it, just call methods on it. But you have
array-like access to the elements as needed.
* Most jQuery code should run only after the DOM content is loaded:
> $(document).ready(function() {
> // your code here
> }
Other Libraries
===============
There are many [other libraries] [Wikipedia Lib list] out there. Some of them
have very good ideas or elegant implementations. A few to note:
* [FuseJS] is presently in alpha mode. John-David Dalton has some beautiful
ideas and seems to have very few axes to grind in his library.
* [Google Closure] has as it's major selling point the fact that it has the giant
Google behind it. The implementation is a mixed bag.
* [Cappuccino], [qooxdoo], and [SproutCore] are entire GUI toolkits written in
Javascript. There are serious cross-browser and future-compatibility concers,
but they might lead to speedy prototyping
* [MyLibrary] has many good ideas and leads the way in some respects, but it is
a one-man show, and that man does not have a reputation for being helpful.
Code Review Excercise
=====================
We're going to take one function, currently in use in a production application
at a large company and point out all sorts of flaws within it. The goal is not to
write a replacement, but just to note the sorts of things that go wrong. At the
end, though, we will present alternate versions.
The thing to note is that this code works. For the expected type of input, it
generates the expected output. It might be a little lacking in error-handling.
It might not gracefully deal with unexpected input. But it does what's expected
of it. The problems are not in functionality but in code design.
The Problem
===========
The function is supposed to so something simple. There are a number of dynamic
data structures that look something like this:
> var itemArray = [
> {"@id": "abc7", other: "props", found: "here"},
> {"@id": "abc42", other: "props", found: "here"},
> {"@id": "abc19", other: "props", found: "here"},
> {"@id": "abc36", other: "props", found: "here"},
> ];
The actual objects are of course more complex. There are arrays containing different types of
objects. One type will have a leading "abc" in the id prefix. Another will have
"xyz", or some other string. Although they are often in order, they could be
randomly arranged. What we want it a function that picks off the numeric
portion of the ids, and returns the largest one.
For the array above, the function should return 42.
The Original Solution
=====================
> 01 function getCurrentId(itemArray) {
> 02 var nextId = 0;
> 03 var ids = [];
> 04 var id = "";
> 06 $(itemArray).each(function (idx) {
> 07 id = this["@id"];
> 08 var regexp = /\d.*/g;
> 09 regexp.compile(regexp);
> 10 ids[idx] = this["@id"].substring(
regexp.exec(id).index, this["@id"].length);
> 11 });
> 13 if (ids.length > 0) {
> 14 nextId = ids.sort(function(a,b){return a-b;})
.reverse()[0];
> 15 }
> 17 return nextId;
> 18 }
Basic Issues
============
Below we will discuss many problems with this code. But one fundamental issue
is that this came with no unit tests and no documentation. To understand it,
we must either investigate the code itself or determine its goals from the
business context. This makes replacing the function with a better equivalent
more difficult than it should be. But it's not too difficult to understand what
the code is doing. So without futher ado, let's look at the problems with it.
These are presented in no particular order.
Variable Naming
===============
We have a function named `getCurrentId`, but on line 02 we introduce a variable
named `nextId`, and end on line 17 by returning it. So which is it, the next id
or the current one? Code inspection tells us that the function is returning the
highest current value, so it's the variable and not the function that should be
renamed.
jQuery (` $ `) Constructor
==========================
In order to use jQuery's `each` function, this function wraps the input array in
a jQuery object, using the ` $ ` alias to the `jQuery` constructor function:
> 06 $(itemArray).each(function (idx) { // ...
The jQuery constructor is an expensive call. It might be justified if this gave
us some functionality that we didn't otherwise have. But all we use is the
`each` function, which is itself exposed as a public utility function in jQuery.
So we could get the same result with this:
> 06 $.each(itemArray, function (idx) { // ...
and not take the expensive constructor hit.
Wrong Array Utility
===================
Lines 03 - 11 can be seen as turning our original structure into an array of numbers.
That is, for input that looks like this:
> [{"@id": "abc10"}, {"@id": "abc42"}, {"@id": "abc19"}, {"@id": "abc36"}];
after line 11, the variable `ids` will contain this:
> [10, 42, 19, 36]
Instead of doing this with `each`, there is another array function, `map`, which
has the purpose of accepting an array and returning an array whose values are
the result of applying a given function to each member of the original array.
So a quick refactoring would lead to somewhat cleaner code:
Code
====
> 03 var id = "";
> 04
> 05 var ids = $.map(itemArray, function (item) {
> 06 id = item["@id"];
> 07 var regexp = /\d.*/g;
> 08 regexp.compile(regexp);
> 09 return item["@id"].substring(regexp.exec(id).index, item["@id"].length);
> 10 });
Of course this is still far from ideal, which we'll see as we proceed.
Unnecessary Use of `this`
=========================
jQuery's utility functions often assign `this` to a useful object. This can
make the code somewhat easier to write. But most often it makes it much harder
to read. There is no good reason to use this style on lines 06 - 11 when the
equivalent can be expressed much more cleanly with another parameter:
> 06 $(itemArray).each(function (idx, item) {
> 07 id = item["@id"];
> 08 var regexp = /\d.*/g;
> 09 regexp.compile(regexp);
> 10 ids[idx] = item["@id"].substring(regexp.exec(id).index, item["@id"].length);
> 11 });
Underused Variable
==================
The variable `id` is defined on line 04, and assigned on line 07 (`id =
this["@id"];`), and then used as a parameter to the `exec` call of the regex.
But twice in line 09, we refer to `this["@id"]` instead of the variable we've
created. Of course this works, but if we were going to do this, and not reuse
the variable, there is no point in creating it.
Bad Regex
=========
The regular expression used accepts many inputs that it should not.
> 08 var regexp = /\d.*/g;
This is the first issue that affects the business logic. And it can be
discovered only by knowing something of the business requirements. What the
regex is supposed to recognize are strings ending in a run of digits. In fact
we know a little more. It will always be a string of letter followed by a
string of digits, but since it's only the final digits we care about, anything
that notes the final string of digits should be fine.
This accepts all sorts of other input. Basically, what this regex matches is any
string that contains a digit. So "a1b2c3" would match. The "`\d`" matches a
digit, "`.*`" matches all subsequent digits, and the "` g `" means this applies
anywhere in the string. One the match is found, the matching index is used with
a `substring` to grab the matching string. Since this starts at the first digit,
"a1b2c3" would return "1b2c3".
A Better Regex
===============
But a better regex would handle all this for us. If our regex looked like this
> 08 var regexp = /\d+$/;
then we could simply do
> 09 var match = this["@id"].match(regexp);
> 10 ids[idx] = (match && match[0]) || 0;
This would avoid all the mucking around with substrings, too.
And while we're on the subject, there is no reason to name this variable
`regexp`. That's like naming a String `string` or a Number `number`. A name
such as `idFormat` would be much more expressive.
Redeclaring and Compiling the Regex in a Loop
=============================================
This code uses the deprecated `compile` method of its regex object. That method no
longer does anything in most Javascript environments. Regular Expressions are
compiled on construction.
But, if it actually did something, it would be very, very poorly placed.
Compiling a regex is an expensive operation. Doing so in a loop, when it
could easily be pulled out of the loop is absurd.
It's not clear whether the regex that's in the code will be compiled once on
the parsing or whenever it's encountered during execution; the spec on that has
changed over time, and it's not at all clear what browser Javascript engines
are doing now. But in any case, this variable should be instantiated before the
loop.
Late `var` declaration
======================
All `var` statements belong at the top of the smallest function scope that use
them. They don't belong further along in the body of the function, especially
not in a loop. Again, the regex is the issue:
> 08 var regexp = /\d.*/g;
Unnecessary Parameters to `substring`
=====================================
`substring` can be called with one or two parameters. The two parameters used
here return a slice of a string starting with the position in the first
parameter and ending before the position in the second parameter. The way this
is done works correctly. But the other version, the one with a single parameter
simply returns the end of the string, starting with the position in the first
parameter.
> "abcdefghijklm".substring(10, 13) // ==> "klm"
> "abcdefghijklm".substring(10) // ==> "klm"
This is a minor issue, but since the code has to determine that last position,
using `this["@id"].length`, the one-parameter code is cleaner, easier to read,
and perhaps slightly more performant:
> ids[idx] = this["@id"].substring(regexp.exec(id).index, this["@id"].length);
> ids[idx] = this["@id"].substring(regexp.exec(id).index);
Late Early-escaping
===================
Early escaping from functions is a legitimate technique. If you know that you
can skip a great deal of the work because of the structure of the input
parameters, it makes sense to either add an early `return` statement or wrap
the remaining body inside an `if`-block.
But placing this code after a great deal of work is done is simply a waste:
> 02 var nextId = 0;
> ... // lots of work here
> 13 if (ids.length > 0) {
> 14 nextId = ids.sort(function(a,b){return a-b;}).reverse()[0];
> 15 }
> 16
> 17 return nextId;
This might be legitimate, except that the array `ids` has by definition, the
same number of elements as the input `itemArray` parameter. So we could have
checked up front if the array was empty:
> 02 if (!itemArray || !itemArray.length) {return 0;}
This would have saved us the instantiations of `ids` and `id`, the construction
of the jQuery wrapper, and the call to the `each` function, all of which offer
us no benefits if the array is empty.
Ignoring Bad Input
==================
While this function does its job as expected with good input, it will throw a
TypeError if one of the elements does not have an "`@id`" property. This could
be the required behavior, but that's unlikely in a consumer-facing application.
And a check of the code that calls this function shows that this exception would
bubble far away. It's almost certainly unintentional. Fixing it might be as
simple as replacing this:
> 07 id = this["@id"];
with this:
> 07 id = this["@id"] || "0";
Of course this would only work if the issue with not actually using the `id`
variable were first resolved.
Using `sort` to Find a Maximum
==============================
Any class on algorithms introduces big-O notation to describe the time various
algorithms take to do a job. An algorithm that is O(n) takes an amount of time
proportional to the the size of input. One that is O(n-squared) takes an amount
of time proportional to the square of the size of the input. A naive sorting
algorithm of O(n-squared). The best ones are O(n * log(n)), which is slower
than linear, but much faster than O(n-squared.)
But finding the maximum of a set should be linear. We should simply be able to
check each one, comparing it to the current maximum.
So if we're using `sort` in order to help us find a maximum, we are almost
certainly using a much larger tool than the job requires.
One thing that is **not** a mistake, although it might look like one, is the
sort function passed to the sort call. It looks like it would be doing the same
thing as the default sort, but by using the subtraction, it forces its arguments
to numbers and ends up sorting numerically rather than lexicographically.
Using `reverse` and `[0]` to Find the Last Element
==================================================
> 14 nextId = ids.sort(function(a,b){return a-b;}).reverse()[0];
Really? To get the last, we reverse it and then take the first? Why not just
> 14 nextId = ids.sort(function(a,b){return a-b;})[ids.length -1];
This does not involve another function call (which above was an additional O(n)
call.) It involves two property look-ups and a subtraction. This will clearly
be more efficient and is cleaner code.
Breaking a Coherent Process Into Redundant Steps
================================================
Perhaps the biggest problem with this code is its fundamental design. It loops
over the array, extracting the numbers, then sorts the resulting set of numbers,
a process which in some manner involves looping over the numbers, and then
reverses the array, which also involves some sort of looping. But all we're
trying to do is extract the largest number from the set. We should be able to
loop just once, updating the maximum as we find each number, skipping the
secondary array altogether.
For some reason, this simple technique was not noticed. The resulting code was
broken in so many ways but none more than in the overall choice of how to think
about the problem.
Alternate Versions
==================
Much simpler and more explict version of this code might look like one of
the following, depending upon your feelings about one-liners and temporary
variables.
Version 1
=========
> 01 var getCurrentId = (function() {
> 02 var idFormat = /\d+$/
> 03 return function(items) {
> 04 var maximum = 0, i, len, match, id, val;
> 05 for (i = 0, len = items.length; i < len; i++) {
> 06 id = items[i] && items[i]["@id"] || "";
> 07 match = idFormat.exec(id);
> 08 val = Number((match && match[0])) || 0;
> 09 maximum = Math.max(maximum, val);
> 10 }
> 11 return maximum;
> 12 };
> 13 }());
Version 2
=========
> 01 var getCurrentId = (function() {
> 02 var idFormat = /\d+$/
> 03 return function(items) {
> 04 var maximum = 0, i, len, match;
> 05 for (i = 0, len = items.length; i < len; i++) {
> 06 maximum = Math.max(maximum, +((match = idFormat.exec(items[i] &&
> 07 items[i]["@id"] || "")) && match[0]) || 0);
> 08 }
> 09 return maximum;
> 10 };
> 11 }());
Additional Techniques
=====================
Either of these could have an initial check for a zero-element array or a
non-existent parameter if it's deemed that is a likely situation,
but that's probably not necessary as the error checking done inline will just
end up returning zero if it detects those situations or if there is other
unexpected input.
Conclusions
===========
This code was a perfect storm. It's very rare to have so many errors on so few
lines of code. Most of the code in the application is of reasonable quality.
But we should be noticing bad practices. We should be sharing with the team
issues that we see. When we finish a section of code, we should take a little
time to reflect on whether it passes the smell test. We should do this even if
we're pressed for time and coudn't possibly fix it immediately. It should nag at
us and keep us up at nights when this has been in the codebase too long.
Code quality is a job for every programmer.
What's Next?
============
* Speakers?
* In-house Presenters?
* Volunteers?
* Coding Camps?
* Other Ideas?
[About.com: Javascript]: http://javascript.about.com/
[Apple Dashboard Widgets]: http://www.apple.com/downloads/dashboard/
[Brown University CS Department Tutorial]: http://www.cs.brown.edu/courses/bridge/1998/res/javascript/javascript-tutorial.html
[Cappuccino]: http://cappuccino.org/
[comp.lang.javascript]: http://groups.google.com/group/comp.lang.javascript
[crockford misunderstood]: http://www.crockford.com/javascript/javascript.html
[crockford private]: http://www.crockford.com/javascript/private.html
[Crockford's Videos]: http://video.yahoo.com/watch/111587/1027854
[ECMAScript Specification]: http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
[ECMAScript Specification 3]: http://www.mozilla.org/js/language/E262-3.pdf
[Essential JavaScript]: http://www.hunlock.com/blogs/Essential_Javascript_--_A_Javascript_Tutorial
[Eloquent Javascript]: http://eloquentjavascript.net/
[FuseJS]: http://github.com/jdalton/fusejs
[Google Closure]: http://code.google.com/closure/
[High Performance Javascript]: http://shop.oreilly.com/product/9780596802806.do
[Javascript: The Definitive Guide]: http://oreilly.com/catalog/9780596000486
[JavaScript: The Good Parts]: http://oreilly.com/catalog/9780596517748/
[Javascript Patterns]: http://shop.oreilly.com/product/9780596806767.do
[JavaScript Weekly]: http://javascriptweekly.com/
[jQuery]: http://jquery.com/
[JScript documentation]: http://msdn.microsoft.com/en-us/library/hbxc2t98.aspx
[JScript.NET]: http://msdn.microsoft.com/en-us/library/ms974588
[jsmentors]: http://groups.google.com/group/jsmentors/topics
[Markdown]: http://daringfireball.net/projects/markdown/
[Microsoft Gadgets]: http://en.wikipedia.org/wiki/Microsoft_Gadgets
[Mozilla Developer Center]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide
[MyLibrary]: http://www.cinsoft.net/mylib.html
[Node]: http://nodejs.org/
[Rhino]: http://www.mozilla.org/rhino/
[Quirksmode]: http://www.quirksmode.org/
[qooxdoo]: http://qooxdoo.org/
[S5]: http://meyerweb.com/eric/tools/s5/
[Secrets of the JavaScript Ninjas]: http://jsninja.com/
[Server-side environments]: http://en.wikipedia.org/wiki/Comparison_of_Server-side_JavaScript_solutions
[Showdown]: http://attacklab.net/showdown/
[SproutCore]: http://www.sproutcore.com/
[Test-Driven JavaScript Developement]: http://tddjs.com/
[w3Schools.com]: http://www.w3schools.com/js/default.asp
[webref closure]: http://www.webreference.com/programming/javascript/rg36/
[Wikipedia Lib list]: http://en.wikipedia.org/wiki/List_of_JavaScript_libraries
[Yahoo! Messenger]: http://developer.yahoo.net/blog/archives/2010/06/ymessenger_api.html