The .selector property stored the CSS selector string originally passed to jQuery() when a collection was created. This tutorial covers reading it in jQuery 1.x/2.x, why it becomes unreliable after .find() and other traversal, the official plugin parameter pattern, and what to do in jQuery 3.0+ after the property was removed.
01
String
Query text
02
Since 1.3
Added
03
Creation
Original set
04
Stale
After .find()
05
Plugins
Pass explicitly
06
Removed
jQuery 3.0
Fundamentals
Introduction
When you write $("div.item"), jQuery parses the string "div.item", finds matching elements, and returns a collection object. In jQuery 1.x and 2.x, that collection also exposed .selector — the same string you typed — as read-only metadata.
That sounds convenient for plugins that need to know “which selector built this set.” The catch, documented by jQuery since deprecation in 1.7, is that traversal changes the elements without updating .selector to a trustworthy new query. After $("#menu").find("a"), the set holds anchor tags but .selector may still describe the old #menu selection.
jQuery 3.0 removed .selector entirely. The recommended fix — pass the selector string as an explicit plugin argument — works in every version and avoids silent bugs.
Concept
Understanding the .selector Property
.selector is a string property on jQuery collection instances. It reflects the selector argument to jQuery() at creation time — not a live description of the elements currently in the set after you chain .find(), .filter(), .add(), or .not().
If the collection was built from a DOM node ($(element)), HTML string, or function — without a CSS selector — .selector is typically an empty string.
⚠️
Never re-query from .selector alone
Do not write $(collection.selector) expecting to get the same elements after traversal. Store the selector in your own variable or pass it into plugin methods — the official jQuery documentation has warned about this since 1.7.
Foundation
📝 Syntax
Read the property on a jQuery collection (jQuery 1.3–2.x only):
jQuery
jQueryCollection.selector
Related constructor form
The string you pass here may become .selector on the result:
jQuery
jQuery( selector [, context ] )
Return value
A String — the selector passed when the set was created.
Empty string when no selector string was used (e.g. $(domNode)).
Does not update to reflect elements after traversal methods.
undefined in jQuery 3.0+ — the property was removed.
Two legacy metadata properties — both removed in jQuery 3.0 — and the pattern jQuery recommends instead.
.selector
"div.item"
Original query string
.context
document
Search root DOM node
.length
3
Still exists in jQuery 3.x
Plugin arg
.foo(sel, opts)
Official replacement
Hands-On
Examples Gallery
Examples 1–4 use jQuery 1.12.4 where .selector exists. Example 5 demonstrates the official plugin parameter pattern on jQuery 3.7.1. Reference: jQuery API — .selector.
📚 Getting Started
Read .selector on collections created from CSS selector strings.
Example 1 — Read the Original Selector String
After a straightforward selection, .selector echoes the string you passed to $().
jQuery copies the selector argument onto the collection object at init time. This only works when the set was created from a selector string — not from a wrapped DOM node.
📈 Practical Patterns
Scoped searches, stale metadata after traversal, DOM wraps, and the modern plugin fix.
Example 2 — Scoped jQuery(selector, context)
Passing a container as the second argument limits matches; .selector still stores the query string.
match count: 2
selector string: .tag
context id: sidebar
How It Works
.selector and .context were complementary metadata: what string you searched for, and where you searched. Both were removed in jQuery 3.0; keep your own variables for each.
Example 3 — Why .selector Is Unreliable After .find()
The official docs warn: traversal changes the set without updating .selector meaningfully.
jQuery
var $menu = $("#menu");
var $links = $menu.find("a");
console.log($menu.selector); // "#menu" — OK
console.log($links.selector); // may still be "#menu" or stale
console.log($links.length); // 2 — but these are <a> elements
After $("#menu"):
selector: #menu
length: 1
After .find("a"):
selector: #menu (stale!)
length: 2
How It Works
This is why jQuery deprecated .selector in 1.7. You cannot safely run $($links.selector) and expect anchor tags — the property describes creation history, not current membership.
Example 4 — Empty .selector When Wrapping a DOM Node
$("#box") has a selector string; $(element) often does not.
jQuery
var el = document.getElementById("box");
console.log($("#box").selector); // "#box"
console.log($(el).selector); // "" (empty string)
From $("#box"):
selector: "#box"
From jQuery(el):
selector: ""
How It Works
Plugins that assumed every collection had a non-empty .selector broke when users passed raw DOM nodes. Always validate or require an explicit selector parameter.
Example 5 — Official Plugin Pattern (jQuery 3.7.1)
From the jQuery docs: pass the selector as the first argument to your plugin method.
jQuery
$.fn.highlightBar = function (selector, options) {
var color = (options && options.color) || "#fef08a";
return this.filter(selector).css("background-color", color);
};
$("div.bar").highlightBar("div.bar", { color: "#bbf7d0" });
// Repeat "div.bar" explicitly — do not read this.selector
Plugin received selector: "div.bar"
.selector in jQuery 3.x: undefined (removed)
Both bars highlighted
How It Works
Repeating the selector in the call looks redundant, but it is explicit and version-proof. The caller — not jQuery internals — owns the query string your plugin needs.
Applications
🚀 When You Might Encounter .selector
Legacy jQuery plugins — code written before 1.7 that read this.selector inside $.fn methods.
Debugging old codebases — log creation-time metadata during jQuery 2.x → 3.x upgrades.
Understanding deprecation warnings — jQuery Migrate may flag .selector access.
Teaching collection internals — contrast metadata with live DOM state after traversal.
Writing new plugins — use explicit parameters instead (official recommendation).
Not for re-querying — never treat .selector as the current set’s query.
🧠 How .selector Was Stored (and Why It Failed)
1
Call jQuery("div.item")
jQuery parses the string and finds matching elements.
Init
2
Copy string to .selector
Metadata saved: "div.item" on the collection object.
Store
3
Chain .find() or .filter()
Elements in the set change; .selector often does not.
Stale
4
✅
Removed in 3.0
Pass selector strings explicitly to plugins and helpers.
Important
📝 Notes
Added in jQuery 1.3; deprecated in jQuery 1.7; removed in jQuery 3.0.
Official docs: never a reliable indicator of the current set after traversal.
Related removed property: .context — the DOM search root.
Related still-available property: .length — number of matched elements.
Empty when collection created from DOM node, HTML string, or function — no selector arg.
jQuery Migrate can help locate legacy .selector usage during upgrades.
Compatibility
Browser Support
.selector existed wherever jQuery 1.3–2.x ran on collections built from selector strings. It was deprecated in jQuery 1.7 and removed in jQuery 3.0.
✓ Removed 3.0
jQuery .selector
Available on jQuery 1.12.x and 2.2.x collections only. jQuery 3.7.x has no .selector property — pass selector strings as explicit plugin arguments instead.
LegacyjQuery 1.x / 2.x
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
Reliability after traversalUnreliable
Bottom line: Even when .selector existed, jQuery warned against using it to re-query the current set. Treat it as historical metadata — or better, never depend on it at all.
Wrap Up
Conclusion
.selector stored the CSS query string passed to jQuery() when a collection was first built. It was useful for debugging and seemed helpful for plugins — but jQuery deprecated it because traversal methods changed the matched elements without updating the string to something trustworthy.
jQuery 3.0 removed .selector alongside .context. The durable pattern from the official documentation is simple: if your plugin needs a selector, accept it as a parameter. Explicit beats magical metadata every time.
Pass selector strings as explicit plugin method arguments
Store selectors in your own variables when plugins need them
Search legacy code for .selector during jQuery 3 upgrades
Use .length for match counts — it still works in 3.x
Read the official plugin example on api.jquery.com/selector
❌ Don’t
Re-query with $(collection.selector) after traversal
Assume .selector exists in jQuery 3.x
Expect a non-empty .selector on $(domNode) sets
Confuse .selector with the Selectors API category docs
Build new features on removed collection metadata
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about .selector
Creation-time string — not a live query descriptor.
5
Core concepts
📄01
String
Query text
Type
1.702
Deprecated
Removed 3.0
History
.find03
Stale
After traverse
Trap
fn04
Plugin arg
Official fix
Pattern
""05
Empty
DOM wrap
Edge
❓ Frequently Asked Questions
.selector is a read-only string on jQuery collections (jQuery 1.3 through 2.x) that stores the CSS selector passed to jQuery() when the set was first created — for example $("div.item").selector returns "div.item".
No. jQuery's official docs warn that .selector was never reliable after traversal. Methods like .find(), .filter(), .add(), and .not() change which elements are in the set without updating .selector to a meaningful new query string.
No. .selector was deprecated in jQuery 1.7 and removed in jQuery 3.0 along with .context. Modern plugins should accept the selector string as an explicit method parameter instead of reading it from the collection.
Often an empty string. When no selector string was passed — only a DOM node, HTML snippet, or callback — jQuery had nothing to store in .selector.
.selector holds the query string ("#menu li"). .context holds the DOM node that limited the search. Both were creation-time metadata removed in jQuery 3.0. Scoped selection jQuery(sel, context) still works; reading these properties back does not.
Official jQuery guidance: require the selector as a parameter. Example: $.fn.foo = function(selector, options) { ... }; Usage: $("div.bar").foo("div.bar", { dog: "bark" }); — repeat the selector explicitly rather than relying on collection metadata.
Did you know?
jQuery’s .selector and .context were removed in the same 3.0 cleanup that trimmed internal collection metadata. The jQuery team kept the behaviors beginners rely on — scoped jQuery(selector, context) searches and chainable traversal — while dropping the read-back properties that plugins misused. The official replacement for plugins is deliberately boring: ask the caller to pass the selector string again. Repetition beats hidden state when the hidden state goes stale after .find().