From jQuery to JavaScript: A Reference

Whether we like it or not, more and more developers are being introduced to the world of JavaScript through jQuery first. In many ways, these newcomers are the lucky ones. They have access to a plethora of new JavaScript APIs, which make the process of DOM traversal (something that many folks depend on jQuery for) considerably easier. Unfortunately, they don't know about these APIs!

In this article, we'll take a variety of common jQuery tasks, and convert them to both modern and legacy JavaScript.

Modern vs. Legacy - For each item in the list below, you'll find the modern, "cool kids" way to accomplish the task, and the legacy, "make old browsers happy" version. The choice you choose for your own projects will largely depend on your visitors.


Before We Begin

Please note that some of the legacy examples in this article will make use of a simple, cross-browser, addEvent function. This function will simply ensure that both the W3C-recommended event model, addEventListener, and Internet Explorer's legacy attachEvent are normalized.

So, when I refer to addEvent(els, event, handler) in the legacy code snippets below, the following function is being referenced.


1 - $('#container');

This function call will query the DOM for the element with an id of container, and create a new jQuery object.

Modern JavaScript

querySelector is part of the Selectors API, which provides us with the ability to query the DOM using the CSS selectors that we're already familiar with.

This particular method will return the first element that matches the passed selector.

Legacy

Pay special attention to how you reference the element. When using getElementById, you pass the value alone, while, with querySelector, a CSS selector is expected.


2 - $('#container').find('li');

This time, we're not hunting for a single element; instead, we're capturing any number of list items that are descendants of #container.

Modern JavaScript

querySelectorAll will return all elements that match the specified CSS selector.

Selector Limitations

While nearly all relevant browsers support the Selectors API, the specific CSS selectors you pass are still limited to the capability of the browser. Translation: Internet Explorer 8 will only support CSS 2.1 selectors.

Legacy


3 - $('a').on('click', fn);

In this example, we're attaching a click event listener to all anchor tags on the page.

Modern JavaScript

The above snippet looks scary, but it's not too bad. Because querySelectorAll returns a static NodeList rather than an Array, we can't directly access methods, like forEach. This is remedied by calling forEach on the Array object, and passing the the results of querySelectorAll as this.

Legacy


4 - $('ul').on('click', 'a', fn);

Ahh - this example is slightly different. This time, the jQuery snippet is using event delegation. The click listener is being applied to all unordered lists, however, the callback function will only fire if the target (what the user specifically clicked on) is an anchor tag.

Modern JavaScript

Technically, this vanilla JavaScript method isn't the same as the jQuery example. Instead, it's attaching the event listener directly to the document. It then uses the new matchesSelector method to determine if the target - the node that was clicked - matches the provided selector. This way, we're attaching a single event listener, rather than many.

Please note that, at the time of this writing, all browsers implement matchesSelector via their own respective prefixes: mozMatchesSelector, webkitMatchesSelector, etc. To normalize the method, one might write:

With this technique, in Webkit, matches will refer to webkitMatchesSelector, and, in Mozilla, mozMatchesSelector.

Legacy

As a fallback, we determine if the nodeName property (the name of the target element) is equal to our desired query. Pay special attention to the fact that older versions of Internet Explorer sometimes plays by their own rules - sort of like the kid who eats play-doh during lunch time. You won't be able to access target directly from the event object. Instead, you'll want to look for event.srcElement.


5 - $('#box').addClass('wrap');

jQuery provides a helpful API for modifying class names on a set of elements.

Modern JavaScript

This new technique uses the new classList API to add, remove, and toggle class names.

Legacy

The fallback technique requires just a tad more work, ay?


6 - $('#list').next();

jQuery's next method will return the element that immediately follows the current element in the wrapped set.

Modern JavaScript

nextElementSibling will refer specifically to the next element node, rather than any node (text, comment, element). Unfortunately, Internet Explorer 8 and below do not support it.

Legacy

There's a couple ways to write this. In this example, we're detecting the nodeType of the node that follows the specified element. It could be text, element, or even a comment. As we specifically need the next element, we desire a nodeType of 1. If next.nodeType returns a number greater than 1, we should skip it and keep going, as it's probably a text node.


7 - $('<div id=box></div>').appendTo('body');

In addition to querying the DOM, jQuery also offers the ability to create and inject elements.

Modern JavaScript

There's nothing modern about this example; it's how we've accomplished the process of creating and injecting elements into the DOM for a long, long time.

You'll likely need to add content to the element, in which case you can either use innerHTML, or createTextNode.


8 - $(document).ready(fn)

jQuery's document.ready method is incredibly convenient. It allows us to begin executing code as soon as possible after the DOM has been loaded.

Modern JavaScript

Standardized as part of HTML5, the DOMContentLoaded event will fire as soon as the document has been completed parsed.

Legacy

The fallback solution, every nine milliseconds, will detect the value of document.readyState. If "loading" is returned, the document hasn't yet been fully parsed (/in/.test(). Once it has, though, document.readyState will equal "complete," at which point the user's callback function is executed.


9 - $('.box').css('color', 'red');

If possible, always add a class to an element, when you need to provide special styling. However, sometimes, the styling will be determined dynamically, in which case it needs to be inserted as an attribute.

Modern JavaScript

Once again, we're using the [].forEach.call() technique to filter through all of the elements with a class of box, and make them red, via the style object.

Legacy

This time, we're getting a bit tricky with the while loop. Yes, it's a bit snarky, isn't it? Essentially, we're mimicking:

However, as we only need to perform a single action, we can save a couple lines. Note that readability is far more important than saving two lines - hence my "snarky" reference. Nonetheless, it's always fun to see how condensed you can make your loops. We're developers; we do this sort of stuff for fun! Anyhow, feel free to stick with the for statement version.


10 - $()

Clearly, our intention is not to replicate the entire jQuery API. Typically, for non-jQuery projects, the $ or $$ function is used as shorthand for retrieving one or more elements from the DOM.

Modern JavaScript

Notice that $ is simply a one-character pointer to document.querySelector. It saves time!

Legacy

Unfortunately, the legacy method isn't quite so minimal. Honestly, at this point, you should use a library. jQuery is highly optimized for working with the DOM, which is why it's so popular! The example above will certainly work, however, it doesn't support complex CSS selectors in older browsers; that task is just a wee-bit more complicated!


Summary

It's important for me to note that that I'm not encouraging you to abandon jQuery. I use it in nearly all of my projects. That said, don't always be willing to embrace abstractions without taking a bit of time to research the underlying code.

I'd like this posting to serve as a living document, of sorts. If you have any of your own (or improvements/clarifications for my examples), leave a comment below, and I'll sporadically update this posting with new items. Bookmark this page now! Lastly, I'd like to send a hat-tip to this set of examples, which served as the impetus for this post.

Tags:

Comments

Related Articles