Prototype vs. YUI Round 2: I love $

Probably the most commonly needed Function for a Web Application Developer (WAD), is document.getElementById. As you will most certainly need to retrieve HTMLElements from the DOM by the elements ID. Using getElementById is perfectly valid, but has potential drawbacks such as:

  • document.getElementById is verbose
  • multiple elements cannot be retrieved with one simple call
  • Some browsers, especially old browsers, do not support this call.
  • The more IDs you use in your document, the longer the seek time of this method.

As the title says, I am in love with the $ (I am also in love with money, in case you were wondering). The $ function was first developed by Prototype (and IMHO is Prototypes greatest contribution to the JavaScript community). My love for the $ function is two-fold:

  • It is elegant, simple, and concise
  • Using the $ symbol as a shortcut, should be safe and most people did not know this was possible (so it is cool)

But beyond those points, let us really consider what an element retrieval function should and should not do:


  • Process lists of elements as well (both arguments list and arrays)
  • Handle all x-browser issues and old browsers, or degrade nicely
  • Caching. It is faster to maintain an array for all previously retrieved IDs, than to retrieve them each time
  • Do nothing when passing an HTMLElement (it should be acceptable to use foo= $(foo), just to ensure that is an HTMLElement

Do Nots

  1. Attach a bunch of variables and/or functions to the HTMLElement*
  2. DO NOT do item 1

* This is my single biggest gripe with pretty much all JavaScript Frameworks. Why do each of my HTMLElements need a slew of helper functions that are already available to me elsewhere? I am not that lazy and frankly it is expensive to add Function references to every HTMLElement that I retrieve. Plus: you increase your chances of circular references causing memory leaks, different Frameworks and Toolkits may conflict with each other, and some future version of JavaScript may define that same function.

That said, let us move on to comparing YUI YAHOO.util.Dom.get vs. Prototype $. I have created an simple rating system that I will be using for this and future discussion. I will walk through each Function and rate them using a point system, where you get plus points for each Dos (ex. +1) and minus points for each (ex. -3) Do not used. Here is the newest prototype $ function from version 1.5.1:

Prototype $ Function

function $(element) {
	if (arguments.length > 1) {
		for (var i = 0, elements = [], length = arguments.length; i < length; i++)
		return elements;
	if (typeof element == string)
		{element = document.getElementById(element);}
	return Element.extend(element);

I am happy in this release that they allow you to pass a list of arguments and retrieve multiple HTMLElements at the same time (+1). I am going to give the Function (+1) for using the $ name. However, it does not allow you to pass in an array as an argument, which is important because sometimes you will have gotten your lists of IDs from a method that created an array of Strings (+0) and will be required to use a work around to pass these Strings into this Function. The Function does retrieve arguments that are Strings and returns the non-string Objects (hopefully HTMLElements) (+1). Unfortunately, the method attaches needless and dangerous methods to the HTMLElement that you pass or retrieve (-3). It does not work with old browsers or degrade well (+0) and has no built in caching system (+0). This gives Prototype an overall rating of (0), which is pretty poor.

YUI YAHOO.util.Dom.get Function

get = function(el) {
	if (!el) { return null; } // nothing to work with
	if (typeof el != string && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is
		return el;
	if (typeof el == string) { // ID
		return document.getElementById(el);
	else { // array of IDs and/or elements
		var collection = [];
		for (var i = 0, len = el.length; i < len; ++i) {
			collection[collection.length] = Y.Dom.get(el[i]);
		return collection;

	return null; // safety, should never happen

As with Prototype you are allowed to pass multiple arguments at the same time (+1) and although you cannot pass in an array of arguments, you can pass an argument that is an array, which is more powerful (+1). There is no $ function short-cut (+0), but I always map this method to the $ symbol anyway, so it is really not a big deal. The function does retrieve arguments that are Strings and returns the non-string Objects (hopefully HTMLElements) (+1). It does not attach needless/dangerous methods to the HTMLElement (-0). Unfortunately, it does not work with old browsers (+0) (it does degrade well, by return null for unexpected values) and has no built in caching system (+0). This gives YUI get Function an overall rating of (+3), which is average, however, if you map the $ symbol to the get Function, then it would bump the rating up one, making YUI get Function slightly above average.

Therefore, using my metrics, YUIs get Function is better than Prototypes $ Function. I recommend using the YUI one and mapping it to a function named $ in the global space, emulating Prototype. Not only will you be able to use the concise $ symbol to retrieve HTMLElements, but doing this will allow you to use YUI with some of Prototype-based Toolkits and Frameworks, without the down-side of using Prototype. Obviously, there is a little room for improvement, as there is no caching yet and there is not a work around for browsers that do not support the document.getElementById method. However, 95%+ of internet users (with JavaScript enabled) will have a browser that supports document.getElementById (and this number increases every year), and caching gives a marginal improvement only when repeatedly retrieving the same element using the get Function (and may be detrimental to performance if you use your own caching system).

Lastly, I want to leave you with a slightly modified YUI get function that I use. I use YUIs namespace approach and attach everything to an Object named Core, which I later shortcut key methods (such as get) as part of my JavaScript build process. Here is my method (it will be made available as part of my Core.Util.Dom package after I have further discussed DOM manipulation:

Core.Util.Dom.get: function() {
	var multiArgs = (1 < arguments.length); // arguments is not an Array
	var elem = multiArgs? arguments: arguments[0];

	// nothing to work with
	if (! elem) {
		return null;

	// assume is a DOMElement, but could be any Object
	if (! isString(elem) && ! isArray(elem) && ! multiArgs) {
		return elem;

	// ID
	if (isString(elem)) {
		return document.getElementById(elem);
	// array of IDs and/or elements
	else {
		var collection = [];
		for (var i = 0, j=elem.length; i