When creating new elements (or selecting existing ones), jQuery returns the elements in a collection. Many developers new to jQuery assume that this collection is an array. It has a zero-indexed sequence of DOM elements, some familiar array functions, and a .length
property, after all. Actually, the jQuery object is more complicated than that.
link DOM and DOM Elements
The Document Object Model (DOM for short) is a representation of an HTML document. It may contain any number of DOM elements. At a high level, a DOM element can be thought of as a "piece" of a web page. It may contain text and/or other DOM elements. DOM elements are described by a type, such as <div>
, <a>
, or <p>
, and any number of attributes such as src
, href
, class
and so on. For a more thorough description, refer to the official DOM specification from the W3C.
Elements have properties like any JavaScript object. Among these properties are attributes like .tagName
and methods like .appendChild()
. These properties are the only way to interact with the web page via JavaScript.
link The jQuery Object
It turns out that working directly with DOM elements can be awkward. The jQuery object defines many methods to smooth out the experience for developers. Some benefits of the jQuery Object include:
Compatibility – The implementation of DOM methods varies across browser vendors and versions. The following snippet attempts to set the inner HTML of a <tr>
element stored in target
:
1
2
3
|
|
This works in many cases, but it will fail in most versions of Internet Explorer. In that case, the recommended approach is to use pure DOM methods instead. By wrapping the target
element in a jQuery object, these edge cases are taken care of, and the expected result is achieved in all supported browsers:
1
2
3
4
5
|
|
Convenience – There are also a lot of common DOM manipulation use cases that are awkward to accomplish with pure DOM methods. For instance, inserting an element stored in newElement
after the target
element requires a rather verbose DOM method:
1
2
3
4
5
6
7
|
|
By wrapping the target
element in a jQuery object, the same task becomes much simpler:
1
2
3
4
5
6
7
|
|
For the most part, these details are simply "gotchas" standing between you and your goals.
link Getting Elements Into the jQuery Object
When the jQuery function is invoked with a CSS selector, it will return a jQuery object wrapping any element(s) that match this selector. For instance, writing:
1
2
3
|
|
headings
is now a jQuery object containing all the <h1>
tags already on the page. This can be verified by inspecting the .length
property of headings
:
1
2
3
4
5
|
|
If the page has more than one <h1>
tag, this number will be greater than one. If the page has no <h1>
tags, the .length
property will be zero. Checking the .length
property is a common way to ensure that the selector successfully matched one or more elements.
If the goal is to select only the first heading element, another step is required. There are a number of ways to accomplish this, but the most straight-forward is the .eq()
function.
1
2
3
4
5
|
|
Now firstHeading
is a jQuery object containing only the first <h1>
element on the page. And because firstHeading
is a jQuery object, it has useful methods like .html()
and .after()
. jQuery also has a method named .get()
which provides a related function. Instead of returning a jQuery-wrapped DOM element, it returns the DOM element itself.
1
2
3
|
|
Alternatively, because the jQuery object is "array-like," it supports array subscripting via brackets:
1
2
3
|
|
In either case, firstHeadingElem
contains the native DOM element. This means it has DOM properties like .innerHTML
and methods like .appendChild()
, but not jQuery methods like .html()
or .after()
. The firstHeadingElem
element is more difficult to work with, but there are certain instances that require it. One such instance is making comparisons.
link Not All jQuery Objects are Created ===
An important detail regarding this "wrapping" behavior is that each wrapped object is unique. This is true even if the object was created with the same selector or contain references to the exact same DOM elements.
1
2
3
4
|
|
Although logo1
and logo2
are created in the same way (and wrap the same DOM element), they are not the same object. For example:
1
2
3
|
|
However, both objects contain the same DOM element. The .get()
method is useful for testing if two jQuery objects have the same DOM element.
1
2
3
4
5
6
7
8
9
|
|
Many developers prefix a $
to the name of variables that contain jQuery objects in order to help differentiate. There is nothing magic about this practice – it just helps some people keep track of what different variables contain. The previous example could be re-written to follow this convention:
1
2
3
4
5
6
7
8
9
|
|
This code functions identically to the example above, but it is a little more clear to read.
Regardless of the naming convention used, it is very important to make the distinction between jQuery object and native DOM elements. Native DOM methods and properties are not present on the jQuery object, and vice versa. Error messages like "event.target.closest is not a function"' and "TypeError: Object [object Object] has no method 'setAttribute'" indicate the presence of this common mistake.
link jQuery Objects Are Not "Live"
Given a jQuery object with all the paragraph elements on the page:
1
2
3
|
|
…one might expect that the contents will grow and shrink over time as <p>
elements are added and removed from the document. jQuery objects do not behave in this manner. The set of elements contained within a jQuery object will not change unless explicitly modified. This means that the collection is not "live" – it does not automatically update as the document changes. If the document may have changed since the creation of the jQuery object, the collection should be updated by creating a new one. It can be as easy as re-running the same selector:
1
2
3
|
|
link Wrapping Up
Although DOM elements provide all the functionality one needs to create interactive web pages, they can be a hassle to work with. The jQuery object wraps these elements to smooth out this experience and make common tasks easy. When creating or selecting elements with jQuery, the result will always be wrapped in a new jQuery object. If the situation calls for the native DOM elements, they may be accessed through the .get()
method and/or array-style subscripting.