The .end() traversing method pops jQuery’s internal selection stack and restores the matched set from before the most recent filtering step. This tutorial covers the official two-list .find() chain, paragraph border demo, stack visualization, compare with .addBack(), and nested .end() patterns.
01
Syntax
.end()
02
Pop stack
One level
03
After find
Go back
04
Chaining
No variables
05
vs addBack
Restore vs merge
06
Since 1.0
Core API
Fundamentals
Introduction
jQuery chaining is powerful: start with a selector, narrow with .find(), .filter(), or .children(), then style the result. But what if the next step needs the original matched set — not the narrowed subset? That is where .end() comes in.
Available since jQuery 1.0, .end() ends the most recent filtering operation and returns the collection to its previous state. Think of it as closing a nested block: each filtering method pushes a new set onto an internal stack, and .end() pops it back off.
Concept
Understanding the .end() Method
Most jQuery DOM traversal methods produce a new jQuery object matching a different set of elements. jQuery maintains a stack of previous sets inside the object. When you call .end(), the current set is discarded and replaced by the set from one level earlier.
.end() takes no arguments and does not modify the DOM — it only changes which elements the jQuery object refers to. It is most useful during method chaining when you want to avoid storing intermediate collections in variables.
💡
Beginner Tip
Picture nested boxes: .find() opens an inner box; .end() closes it and returns to the outer box. Multiple .end() calls close multiple levels.
Foundation
📝 Syntax
General form of .end:
jQuery
.end()
Parameters
None — .end() does not accept any arguments.
Return value
The previous jQuery object from the internal stack — the matched set before the most recent filtering operation.
Official jQuery API two-list chain
jQuery
$( "ul.first" )
.find( ".foo" )
.css( "background-color", "red" )
.end()
.find( ".bar" )
.css( "background-color", "green" );
// .foo red inside first ul only
// .bar green inside first ul only (end restored ul.first)
First list: .foo → red, .bar → green
Second list: no colors (end restored ul.first scope)
How It Works
Without .end(), the second .find(".bar") would search inside the .foo elements — not the whole first list. .end() pops back to ul.first before the second find.
Example 2 — Official Demo: Border on Paragraphs, Not Spans
Find spans inside paragraphs, then .end() to restore the paragraph set and apply a red border — official Example 2.
Every p element gets a red border.
Inner span elements → no border.
How It Works
The intermediate .find("span") does not need styling here — it demonstrates navigating into a subset and returning. After .end(), .css() targets all matched p elements again.
📈 Practical Patterns
Stack visualization, comparison with .addBack(), and nested chains.
Example 3 — Official Demo: Visualize the Stack with Tag Names
Track which elements are in the jQuery object at each chain step — official Example 1 pattern with showTags.
jQuery
jQuery.fn.showTags = function ( n ) {
var tags = this.map( function () { return this.tagName; } )
.get().join( ", " );
$( "b" ).eq( n ).text( tags );
return this;
};
$( "p" )
.showTags( 0 ) // P, P
.find( "span" )
.showTags( 1 ) // SPAN, SPAN, SPAN
.css( "background", "yellow" )
.end()
.showTags( 2 ) // P, P again
.css( "font-style", "italic" );
li → red text
ul → blue border (first end)
#panel → padding (second end)
How It Works
Each filtering method pushes onto the stack. The first .end() returns from li to ul; the second returns from ul to #panel — like closing two nested blocks.
Applications
🚀 Common Use Cases
Multi-step styling — style a subset, restore, style a different subset in the same container.
Avoid temp variables — keep long chains readable without var $parent = ....
After .find() / .filter() — return to the pre-filter matched set for the next operation.
Plugin development — narrow internally, then .end() to preserve caller chain context.
Visual symmetry — pair each narrowing method with a closing .end() for readable block structure.
.find(), .filter(), etc. push new subset onto stack.
Stack: [A, B]
3
.end() pops
Current set B discarded; A becomes active again.
Stack: [A]
4
🖼
Continue chaining
Next method operates on restored set A.
Important
📝 Notes
Available since jQuery 1.0; works in all jQuery 1.x, 2.x, and 3.x versions.
Takes no arguments — always pops exactly one stack level.
Does not modify the DOM — only changes the active jQuery collection.
Methods like .css() and .each() do not push onto the stack — only filtering/traversal methods that change the matched set do.
Calling .end() when the stack is empty returns an empty jQuery object.
For merging previous + current sets, use .addBack() instead of .end().
Compatibility
Browser Support
.end() has been part of jQuery since 1.0+. It is an internal stack operation with no browser-specific behavior.
✓ jQuery 1.0+
jQuery .end()
Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers and IE with supported jQuery builds. No native DOM equivalent — use variables or separate queries instead.
100%With jQuery loaded
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
.end()Universal
Bottom line: Safe in any jQuery project. Use .end() to restore previous sets during chaining; use .addBack() when you need both sets merged.
Wrap Up
Conclusion
The jQuery .end() method restores the matched set from before the most recent filtering step by popping one level off the internal selection stack. It is essential for readable multi-step chains without temporary variables.
Remember the official two-list lesson: after styling .foo, .end() brings you back to ul.first so the next .find(".bar") searches the whole first list — not inside the red .foo items. When you need both parent and child, use .addBack() instead.
Use .end() after .find() when the next step needs the parent set
Pair each narrowing step with .end() for readable nested chains
Prefer variables over deep stacks when chains exceed three levels
Use .addBack() when you need both previous and current elements
Visualize the stack when debugging unexpected selectors
❌ Don’t
Expect .end() to merge sets — that is .addBack()
Call .end() after methods that do not change the matched set
Build chains so long that stack depth becomes hard to track
Forget that without .end(), the next method targets the narrowed subset
Overuse .end() at the very end of a chain when the object is discarded anyway
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about .end()
Pop the stack, restore the previous set.
5
Core concepts
🖼01
.end()
Pop stack
API
↩02
Restore
Previous set
Action
🔗03
Chaining
No vars
Pattern
+04
addBack
Merge both
Compare
2×05
Nested
Multi end()
Depth
❓ Frequently Asked Questions
.end() ends the most recent filtering operation in the current chain and returns the matched set to its previous state. It pops one level off jQuery's internal selection stack — for example, after .find() narrows the set, .end() restores the elements from before that .find().
.end() replaces the current set with the previous set only — the narrowed subset is discarded from the jQuery object. .addBack() merges the previous set with the current set so both groups remain. Use .end() when you only need the earlier selection; use .addBack() when you need both.
Use .end() when chaining multiple filtering steps and you need to return to an earlier matched set without storing it in a variable — for example, styling .foo inside a list, then .end(), then styling .bar in the same original container.
No. .end() takes no parameters. It always pops exactly one level from the internal stack.
Yes. Each .end() pops one more level off the stack. A chain with two .find() calls can use two .end() calls to return to the original set — like closing nested blocks of code.
Usually no. Without chaining, you can save $('ul.first') in a variable and reuse it. .end() is most valuable when exploiting jQuery's method chaining to avoid extra variables.
Did you know?
jQuery’s documentation compares a long chain with .end() to structured code with nested blocks — each .find() opens a block and each .end() closes it. Some developers add a final .end() purely for visual symmetry even when the jQuery object is immediately discarded, though that extra call has a tiny performance cost.