Calling jQuery .end() Without Traversal Operations
Calling the jQuery .end() method without a preceding
traversal or filtering method causes jQuery to return an empty jQuery
object. This article explores how jQuery manages its internal selection
stack using the prevObject property, what happens under the
hood when .end() is invoked prematurely, and how this
behavior affects the rest of your chained script.
How jQuery Manages Traversal History
jQuery tracks changes to the selected elements using an internal
stack. Whenever you invoke a "destructive" traversal method—such as
.find(), .filter(), .children(),
or .parent()—jQuery constructs a new jQuery object
containing the matched elements and attaches a reference to the previous
collection in an internal property named prevObject.
The .end() method is designed to pop the current
selection off this stack and return the previous jQuery object stored in
prevObject.
The Result of Calling .end() Without Traversal
When you initialize a jQuery object directly using a selector (for
example, $('div')), jQuery creates the primary collection.
At this initial stage, there is no previous traversal state. To maintain
consistent object structure, jQuery sets the initial
prevObject to an empty jQuery object (or one referencing
the document context with an element count of zero).
If you call .end() immediately on this base
selection:
const $elements = $('div').end();
console.log($elements.length); // Outputs: 0Because there is no preceding DOM traversal operation to revert to,
.end() resolves to that base prevObject,
returning a jQuery wrapper that contains zero elements.
Impact on Chained Operations
JavaScript will not throw an error if you call .end()
without a prior traversal step. Instead, the method fails silently by
passing an empty set down the chain. Any subsequent methods applied to
the chain will execute against zero nodes:
// The .hide() method does nothing because .end() emptied the selection
$('div').end().hide(); In this scenario, .hide() executes without errors, but
no div elements on the page will actually be hidden because
the active selection was cleared by .end().
Proper Usage
To avoid unintentionally emptying your element set, ensure every
.end() call is paired with a prior filtering or traversal
operation. Only use .end() when you need to step back out
of a nested selection context and return to the parent or broader
matched set previously targeted in the chain.