Understanding the jQuery $.expr Object

The jQuery $.expr object is the internal storage mechanism for jQuery's selector engine, historically powered by Sizzle. It defines how jQuery parses, interprets, and matches elements against CSS selectors. By interacting directly with $.expr, developers can extend jQuery's native selection capabilities and create custom pseudo-class selectors tailored to specific application needs.

What is $.expr?

In jQuery, standard selectors like #id, .class, or div are processed using standard DOM methods like querySelector or querySelectorAll. However, jQuery also supports custom, non-standard pseudo-selectors such as :visible, :hidden, :input, and :even.

These custom pseudo-selectors are registered within the $.expr object. Specifically, $.expr[':'] (an alias for $.expr.pseudos in jQuery 1.8 and later) holds the collection of selector functions that jQuery evaluates when scanning DOM nodes.

The Primary Purpose: Creating Custom Selectors

The main practical purpose of $.expr for developers is creating custom pseudo-selectors to simplify repetitive filtering logic. Instead of chaining methods like .filter(), you can embed the logic directly into selector strings.

Basic Syntax and Example

A custom selector is created by attaching a new function to $.expr[':']. The function must evaluate an element and return true if it matches, or false if it does not.

Here is an example that creates a :caseContains selector, allowing case-insensitive text matching:

jQuery.expr[':'].caseContains = function(elem, index, match) {
  var searchText = match[3];
  return (elem.textContent || elem.innerText || "")
    .toLowerCase()
    .indexOf(searchText.toLowerCase()) >= 0;
};

// Usage:
$('p:caseContains("jquery")').addClass('highlight');

Anatomy of a Selector Function

When defining a custom selector in $.expr, the callback function receives several arguments:

  1. elem: The current DOM element being tested.
  2. index: The zero-based index of the element within the loop.
  3. match: An array containing regex match information. The most commonly used element is match[3], which captures any parameter passed inside the parentheses of the pseudo-selector (e.g., the "jquery" in :caseContains("jquery")).

Why Use $.expr?

  • Code Readability: Custom selectors make queries declarative and clean (e.g., $('a:external') instead of running loops or custom .filter() checks).
  • Reusability: Once added to $.expr, the selector is globally available throughout your application wherever jQuery selectors are accepted.
  • Component-Level Filtering: You can create domain-specific selectors, such as :overdue, :validated, or :inline, making DOM traversal intuitive for teams working on large codebases.