jQuery Source Code Architecture Explained

This article breaks down the internal architecture of the jQuery source code, detailing how the library is structured, initialized, and executed. It covers the core design patterns used by jQuery, including its Immediately Invoked Function Expression (IIFE) wrapper, the factory pattern that eliminates the need for the new keyword, the prototype alias mechanism (jQuery.fn), the internal extension system, and how specialized sub-modules like Sizzle, the Event system, and Ajax interact to create a cohesive, chainable library.

The Self-Executing Wrapper (IIFE)

The entirety of jQuery's source code is wrapped in an Immediately Invoked Function Expression (IIFE) or Universal Module Definition (UMD) pattern. This pattern prevents variable leakage into the global scope and encapsulates internal implementation details.

(function(global, factory) {
    "use strict";
    if (typeof module === "object" && typeof module.exports === "object") {
        // CommonJS / Node environment
        module.exports = global.document ?
            factory(global, true) :
            function(w) {
                if (!w.document) {
                    throw new Error("jQuery requires a window with a document");
                }
                return factory(w);
            };
    } else {
        // Browser environment
        factory(global);
    }
})(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
    // jQuery core implementation lives here
});

By passing window (or global) into the factory function, jQuery localizes the reference, which speeds up variable resolution and enables minifiers to compress the reference into a single character.

The Factory Function and Prototype Architecture

One of jQuery's defining design choices is allowing users to invoke $() without typing new $(). To accomplish this, jQuery uses a factory pattern linked directly to its prototype.

  1. jQuery Declaration: The jQuery variable is defined as a function that returns an instance of an internal constructor named jQuery.fn.init.
  2. jQuery.fn Alias: jQuery sets jQuery.fn = jQuery.prototype as a shorthand.
  3. init Prototype Reassignment: The prototype of jQuery.fn.init is pointed back to jQuery.fn.
var jQuery = function(selector, context) {
    return new jQuery.fn.init(selector, context);
};

jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    length: 0,
    // core prototype methods...
};

var init = jQuery.fn.init = function(selector, context, root) {
    // DOM selection and parsing logic
    return this;
};

// Crucial link: allows instances created by init to inherit jQuery.fn methods
init.prototype = jQuery.fn;

When a user calls $('div'), an instance of init is instantiated, but because init.prototype references jQuery.fn, the returned object inherits all jQuery methods.

Method Chaining

jQuery enables fluent chaining by ensuring that methods that mutate or query the collection return the calling instance (this). If a method creates a new set of elements (such as .find() or .filter()), it builds a new jQuery instance using .pushStack(), which maintains a reference to the previous state (prevObject) so users can revert back using .end().

The Extension Mechanism: jQuery.extend

The extend method is the structural engine for modularity in jQuery. It merges the contents of two or more objects together into the first object.

  • jQuery.extend: Extends the jQuery static object directly with utility methods (e.g., $.ajax, $.each).
  • jQuery.fn.extend: Extends the jQuery prototype, adding instance methods available to element collections (e.g., .addClass, .css).

Both functions point to the exact same implementation:

jQuery.extend = jQuery.fn.extend = function() {
    // Copies properties from source objects to target object
};

This single method serves as both the internal module assembler and the external plugin interface.

Modular Sub-Systems

The jQuery codebase divides its responsibilities into separate, decoupled modules:

  • Core & Accessors: Handles instance creation, type checking, iteration (each, map), and array manipulation.
  • Selector Engine (Sizzle): An integrated engine (or modern querySelectorAll wrapper) that parses complex CSS selectors and traverses the DOM.
  • Data Storage (Data): Manages metadata associated with DOM elements without creating memory leaks caused by circular references between JavaScript and DOM objects.
  • Callbacks & Deferreds: A custom implementation of asynchronous control flow and promises that powers both internal queues and external API operations.
  • Queue: Manages execution queues, heavily used by the animation subsystem.
  • Event System: Normalizes cross-browser event handling, bubbling, and delegation via an internal cache rather than binding directly to raw DOM nodes repeatedly.
  • DOM Manipulation: Methods for inserting, wrapping, cloning, and removing DOM nodes safely, managing cleanup of event listeners and cached data.
  • CSS & Dimensions: Computes style values, polyfills browser quirks, and retrieves layout dimensions (width, height, offsets).
  • Ajax: Implements XMLHttpRequest wrappers with support for custom data transports, JSONP, and promises.

Global Exposure and noConflict

At the conclusion of the factory function, jQuery binds itself to the global environment while saving any prior values assigned to $ or jQuery to support multi-library compatibility:

var _jQuery = window.jQuery,
    _$ = window.$;

jQuery.noConflict = function(deep) {
    if (window.$ === jQuery) {
        window.$ = _$;
    }
    if (deep && window.jQuery === jQuery) {
        window.jQuery = _jQuery;
    }
    return jQuery;
};

if (!noGlobal) {
    window.jQuery = window.$ = jQuery;
}

This allows developers to relinquish control of the $ shortcut back to other libraries (such as Prototype or MooTools) when required.