Skip to content

Commit 58da84d

Browse files
committed
Merge pull request jquery#113 from jugglinmike/issue-95-jquery-object-2
New article: The jQuery Object
2 parents 60b60c1 + 63b5204 commit 58da84d

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
---
2+
level : beginner
3+
title : The jQuery Object
4+
attribution: Mike Pennisi
5+
github : jugglinmike
6+
---
7+
When creating new elements (or selecting existing ones), jQuery returns the elements in a collection.
8+
Many developers new to jQuery assume that this collection is an array.
9+
It has a zero-indexed sequence of DOM elements, some familiar array functions, and a `length` property, after all.
10+
Actually, the jQuery object is more complicated than that.
11+
12+
### What is a DOM element? What is the DOM, for that matter?
13+
14+
The DOM (short for Document Object Model) is a representation of an HTML document.
15+
It may contain any number of DOM elements.
16+
At a high level, a DOM element can be thought of as a "piece" of a web page.
17+
It may contain text and/or other DOM elements.
18+
It is described by a type (i.e. "div", "a", "p", etc.) and any number of attributes (i.e. "src", "href", "class", etc.).
19+
For a more thorough description, please refer to [the official specification from the W3C](http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614).
20+
21+
Elements have properties like any JavaScript object.
22+
Among these properties are attributes like `tagName` and methods like `appendChild`.
23+
These properties are the only way to interact with the web page via JavaScript.
24+
25+
### Why not just put the elements in an array?
26+
27+
It turns out that working directly with DOM elements can be quite awkward.
28+
The jQuery object defines [a ton](http://api.jquery.com/) of methods to smooth out the experience for developers.
29+
For example:
30+
31+
*Compatibility*
32+
The implementation of element methods varies across browser vendors and versions.
33+
The following snippet attempts to set the inner HTML of a `tr` element stored in `target`:
34+
35+
<javascript caption="Setting the inner HTML with the native DOM API">
36+
var target = document.getElementById("target");
37+
target.innerHTML = "<td>Hello <b>World</b>!</td>";
38+
</javascript>
39+
40+
This works in many cases, but it will fail in most versions of Internet Explorer.
41+
In that case, the [recommended approach](http://www.quirksmode.org/dom/w3c_html.html) is to use pure DOM methods instead.
42+
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:
43+
44+
<javascript caption="Setting the inner HTML with jQuery">
45+
var target = document.getElementById("target");
46+
$( target ).html( "<td>Hello <b>World</b>!</td>");
47+
</javascript>
48+
49+
*Convenience*
50+
There are also a lot of common DOM manipulation use cases that are awkward to accomplish with pure DOM methods.
51+
For instance, inserting an element stored in `newElement` after the `target` element requires a rather verbose DOM method:
52+
53+
<javascript caption="Inserting a new element after another with the native DOM API">
54+
var target = document.getElementById("target");
55+
var newElement = document.createElement("div");
56+
target.parentNode.insertBefore( target.nextSibling, newElement )
57+
</javascript>
58+
59+
By wrapping the `target` element in a jQuery object, the same task becomes much simpler:
60+
61+
<javascript caption="Inserting a new element after another with jQuery">
62+
var target = document.getElementById("target");
63+
var newElement = document.createElement("div");
64+
$( target ).after( newElement );
65+
</javascript>
66+
67+
For the most part, these details are simply "gotchas" standing between a developer and her goals.
68+
69+
### Getting stuff in there
70+
71+
When the jQuery function is invoked with a CSS selector, it will return a jQuery object wrapping any element(s) that match this selector.
72+
For instance, by writing
73+
74+
<javascript caption="Selecting all 'h1' tags">
75+
var allHeaders = $("h1");
76+
</javascript>
77+
78+
`headers` is now a jQuery element containing *all* the `<h1>` tags already on the page.
79+
This can be verified by inspecting the `length` property of `headers`:
80+
81+
<javascript caption="Viewing the number of 'h1' tags on the page">
82+
var allHeaders = $("h1");
83+
alert( allHeaders.length );
84+
</javascript>
85+
86+
If the page has more than one `<h1>` tag, this number will be greater than one.
87+
Likewise, if the page has no `<h1>` tags, the `length` property will be zero.
88+
Checking the `length` property is a common way to ensure that the selector successfully matched one or more elements.
89+
90+
If the goal is to select only the first header element, another step is required.
91+
There are a number of ways to accomplish this, the most straight-forward may be the `eq()` function.
92+
93+
<javascript caption="Selecting only the first 'h1' element on the page (in a jQuery object)">
94+
var headers = $("h1");
95+
var firstHeader = headers.eq(0);
96+
</javascript>
97+
98+
Now `firstHeader` is a jQuery object containing only the first `<h1>` element on the page.
99+
And because `firstHeader` is a jQuery object, it has useful methods like `html()` and `after()`.
100+
jQuery also has a method named `get()` which provides a related function.
101+
Instead of returning a jQuery-wrapped DOM element, it returns the DOM element itself.
102+
103+
<javascript caption="Selecting only the first 'h1' element on the page">
104+
var firstHeaderElem = $("h1").get(0);
105+
</javascript>
106+
107+
Alternatively, because the jQuery object is "array-like", it supports array subscripting via brackets:
108+
109+
<javascript caption="Selecting only the first 'h1' element on the page (alternate approach)">
110+
var firstHeaderElem = $("h1")[0];
111+
</javascript>
112+
113+
In either case, `firstHeaderElem` contains the "native" DOM element.
114+
This means it has DOM properties like `innerHTML` and methods like `appendChild()`, but *not* jQuery methods like `html()` or `after()`.
115+
As discussed earlier, the element is more difficult to work with, but there are certain instances that require it.
116+
One such instance is making comparisons.
117+
118+
### Not all jQuery objects are created `===`
119+
120+
An important detail regarding this "wrapping" behavior is that each wrapped object is unique.
121+
This is true *even if the object was created with the same selector or contain references to the exact same DOM elements*.
122+
123+
<javascript caption="Creating two jQuery objects for the same element">
124+
var logo1 = $("#logo");
125+
var logo2 = $("#logo");
126+
</javascript>
127+
128+
Although `logo1` and `logo2` are created in the same way (and wrap the same DOM element), they are not the same object.
129+
For example:
130+
131+
<javascript caption="Comparing jQuery object">
132+
alert( $("#logo") === $("#logo") ); // alerts 'false'
133+
</javascript>
134+
135+
However, both objects contain the same DOM element.
136+
The `get` method is useful for testing if two jQuery objects have the same DOM element.
137+
138+
<javascript caption="Comparing DOM elements">
139+
var logo1 = $("$logo");
140+
var logo1Elem = logo1.get(0);
141+
142+
var logo2 = $("#logo");
143+
var logo2Elem = logo2.get(0);
144+
145+
alert( logo1Elem === logo2Elem ); // alerts 'true'
146+
</javascript>
147+
148+
Many developers prefix a `$` to the name of variables that contain jQuery objects in order to help differentiate.
149+
There is nothing magic about this practice--it just helps some people to keep track of what different variables contain.
150+
The previous example could be re-written to follow this convention:
151+
152+
<javascript caption="Comparing DOM elements (with more readable variable names)">
153+
var $logo1 = $("#logo");
154+
var logo1 = $logo1.get(0);
155+
156+
var $logo2 = $("#logo");
157+
var logo2 = $logo2.get(0);
158+
159+
alert( logo1 === logo2 ); // alerts 'true'
160+
</javascript>
161+
162+
This code functions identically to the example above, but it is a little more clear to read.
163+
164+
Regardless of the naming convention used, it is very important to make the distinction between jQuery object and native DOM elements!
165+
Native DOM methods and properties are not present on the jQuery object, and vice versa.
166+
**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.**
167+
168+
### jQuery objects are not "live"
169+
170+
Given a jQuery object with all the paragraph elements on the page:
171+
172+
<javascript caption="Selecting all 'p' elements on the page">
173+
var allParagraphs = $("p");
174+
</javascript>
175+
176+
...one might expect that the contents will grow and shrink over time as `<p>` elements are added and removed from the document.
177+
This is how "nodelists" returned by the `getElementsByTagName` method work, after all.
178+
179+
jQuery objects do **not** behave in this manner.
180+
The set of elements contained within a jQuery object will not change unless explicitly modified.
181+
This means that the collection is not "live"--it does not automatically update as the document changes.
182+
If the document may have changed since the creation the jQuery object, the collection should be updated by creating a new one!
183+
It can be as easy as re-running the same selector:
184+
185+
<javascript caption="Updating the selection">
186+
allParagraphs = $("p");
187+
</javascript>
188+
189+
### Wrapping up
190+
191+
Although DOM elements provide all the functionality one needs to create interactive web pages, they can be a hassle to work with.
192+
The jQuery object wraps these elements to smooth out this experience and make common tasks easy.
193+
When creating or selecting elements with jQuery, the result will always be wrapped in a new jQuery object.
194+
If the situation calls for the native DOM elements, they may be accessed through the `get()` method and/or array-style subscripting.
195+
196+
These distinctions may not be immediately obvious, but understanding them is an important step in fully utilizing jQuery as it was intended.

0 commit comments

Comments
 (0)