Native JavaScript Equivalents of jQuery Methods: the DOM and Forms

Craig Buckler
Share

The debate is still raging on my recent Do You Really Need jQuery? article but, in summary, there are two reasons why using jQuery is a good idea:

  1. you need to support IE6/7/8 (remember you can’t migrate to jQuery 2.0), or
  2. without jQuery, you’d spend longer writing a jQuery-like library than developing your application.

For everything else, be pragmatic. jQuery is a 270Kb generic library. You are unlikely to require all the functionality it provides and, even if you omit certain modules, it remains a sizable quantity of code. You may load the 30Kb minified version from a CDN but the browser must halt processing and parse the code on every page before doing anything else.

This is the first in a series of articles showing native JavaScript equivalents of common jQuery methods. While you might wish to wrap some of these in shorter alias-like functions, you certainly don’t need to create your own jQuery-like libraries.

DOM Selectors

jQuery permits DOM node selection using CSS selector syntax, e.g.

// find all paragraphs with the class "summary" in the article with ID "first"
var n = $("article#first p.summary");

The native equivalent:

var n = document.querySelectorAll("article#first p.summary");

document.querySelectorAll is implemented in all modern browsers and IE8 (although that only supports CSS2.1 selectors). jQuery has additional support for more advanced selectors but, for the most part, it’ll be running document.querySelectorAll inside the $() wrapper.

Native JavaScript also provides four alternatives which will almost certainly be faster than querySelectorAll if you can use them:

  1. document.querySelector(selector) — fetches the first matching node only
  2. document.getElementById(idname) — fetches a single node by its ID name
  3. document.getElementsByTagName(tagname) — fetches nodes matching an element (e.g. h1, p, strong, etc).
  4. document.getElementsByClassName(class) — fetches nodes with a specific class name

The getElementsByTagName and getElementsByClassName methods can also be applied to single nodes to limit the result to descendants only, e.g.

var n = document.getElementById("first");
var p = n.getElementsByTagName("p");

Let’s do some testing. I wrote a small selection of scripts to retrieve all the comment nodes from my Do You Really Need jQuery? article 10,000 times. The result:

code time
// jQuery 2.0
var c = $("#comments .comment");
4,649 ms
// jQuery 2.0
var c = $(".comment");
3,437 ms
// native querySelectorAll
var c = document.querySelectorAll("#comments .comment");
1,362 ms
// native querySelectorAll
var c = document.querySelectorAll(".comment");
1,168 ms
// native getElementById / getElementsByClassName
var n = document.getElementById("comments");
var c = n.getElementsByClassName("comment");
107 ms
// native getElementsByClassName
var c = document.getElementsByClassName("comment");
75 ms

I can’t claim strict laboratory conditions and it doesn’t reflect real-world usage but, in this situation, native JavaScript was up to 60x faster. It also illustrates that fetching nodes by ID, tag or class will normally be preferable to querySelectorAll.

DOM Manipulation

jQuery offers several methods for adding further content to the DOM, e.g.

$("#container").append("<p>more content</p>");

Beneath the surface, jQuery uses the native innerHTML method, e.g.

document.getElementById("container").innerHTML += "<p>more content</p>";

You can also use DOM building techniques. These are safer but rarely faster than innerHTML:

var p = document.createElement("p");
p.appendChild(document.createTextNode("more content");
document.getElementById("container").appendChild(p);

We can also remove all child nodes in jQuery:

$("#container").empty();

The native equivalent using innerHTML:

document.getElementById("container").innerHTML = null;

or a small function:

var c = document.getElementById("container");
while (c.lastChild) c.removeChild(c.lastChild);

Finally, we could remove the whole element from the DOM in jQuery:

$("#container").remove();

or native JavaScript:

var c = document.getElementById("container");
c.parentNode.removeChild(c);

Scalable Vector Graphics

The core jQuery library has been developed to work with the current document. SVGs also have a DOM, but jQuery does not offer direct manipulation of these objects because it’s normally necessary to use methods such as createElementNS and getAttributeNS. It can be made to work and several plug-ins are available, but it will be more efficient to roll your own code or use a specialized SVG library such as Raphaël or svg.js.

HTML5 Forms

Even the most basic web application will have a form or two. You should always validate user data server-side but, ideally, you’ll supplement it with client-side validation to capture errors before the form is submitted.

Client-side validation is straight-forward:

  1. You run a function when the form is submitted.
  2. If any issues are encountered, you halt the submission and show an error.

You can use jQuery. You can use native JavaScript. Which should you choose? Neither.

HTML5 has built-in support for various common input types such as emails, telephones, URLs, numbers, times, dates, colors and custom fields based on regular expressions. For example, if you want to force the user to enter an email address, use:

<input type="email" name="email" required="required" />

There’s no need for additional JavaScript or jQuery code unless you require a little more sophistication such as comparing two or more fields or showing custom error messages.

Older browsers (including IE9 and below) do not understand the new types and will revert to standard textual input fields. Those users will fall back to server-side validation; not a great experience but you can apply a shim or hope those people see the light and upgrade.

In my next article, we’ll examine native CSS class manipulation and animation.