Native JavaScript Equivalents of jQuery Methods: the DOM and Forms
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:
- you need to support IE6/7/8 (remember you can’t migrate to jQuery 2.0), or
- 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:
document.querySelector(selector)
— fetches the first matching node onlydocument.getElementById(idname)
— fetches a single node by its ID namedocument.getElementsByTagName(tagname)
— fetches nodes matching an element (e.g. h1, p, strong, etc).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 |
---|---|
|
4,649 ms |
|
3,437 ms |
|
1,362 ms |
|
1,168 ms |
|
107 ms |
|
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:
- You run a function when the form is submitted.
- 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.