jQuery - Use the Source Code!

After debugging a production issue with our product carousels by diving into the Bootstrap carousel source code, I thought it'd be a fun activity to start looking into the source of some other libraries that we use.

The obvious starting point was jQuery, since it's at the core of all our DOM manipulation code we write.

Here's a quick link: https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js

*I didn't get too far into the source since it's a pretty long library, but I did have two interesting take-aways.

1. What is jQuery.fn?

One of the first questions I had in mind was regarding jQuery.fn. I previously knew that writing a jQuery plugin involves defining a new method on the jQuery.fn object, but why, and what is, jQuery.fn?

Near the top of jQuery's source lies the answer (well, part of the answer).

jQuery.fn = jQuery.prototype { ... }  

That makes sense. If we want to create a new plugin that we can use from the jQuery object, we need to add it to jQuery's prototype object.

That's a standard Javascript pattern called the Prototype Pattern.

Still, that seems like a strange pattern of creating a pointer to the jQuery.prototype called jQuery.fn. After a bit of Googling, I came across this Google Groups discussion, jQuery Prototype Magic.

$.prototype wasn't used for anything; instead, every time a jQuery object was created, all of the method references found in $.fn were copied, one by one, into the new jQuery object.

As you can guess, this was a bit slow, and I came up with a patch to use $.prototype in the conventional manner instead of copying all the methods. $.fn was kept as an alias of $.prototype for compatibility with existing plugins that already used $.fn.

**So the main take away is, jQuery.fn points to jQuery.prototype, and jQuery.fn is still used for backwards compatibility sake.

2. $(...) doesn't 'technically' return a jQuery object

// Define a local copy of jQuery
var jQuery = function( selector, context ) {

        // The jQuery object is actually just the
        // init constructor 'enhanced'
        return new jQuery.fn.init( selector, context );

var init = jQuery.fn.init = function(...) {...};

init.prototype = jQuery.fn;  

We're all taught that when we use the $(...) selector, jQuery returns a new jQuery object with a collection of elements for you to act on.

Interestingly though, jQuery's source reveals that the constructor is actually jQuery.fn.init. So 'technically', we're actually getting back a new jQuery.fn.init object.

That leads to another interesting line of code:

init.prototype = jQuery.fn;  

The reason for this line of code explained by the 4 things that happen when we use the new operator in Javascript

  1. A new object is created, inheriting from the constructor's prototype
  2. The constructor function is called with any specified arguments
  3. this is bound to the newly created object
  4. The newly created object is returned

So, new jQuery.fn.init( selector, context ) returns a new jQuery.fn.init object. However, the prototype of jQuery.fn.init is empty.

Since we want our new jQuery object to have access to all the useful jQuery methods that we know and love like .find() and .addClass(), the prototype of init needs to point to jQuery's prototype in access jQuery's other methods.

You can think of

init.prototype = jQuery.fn;  

to be re-written as

jQuery.prototype.init.prototype = jQuery.prototype  

Whew, that was a mouthful, but hopefully that sheds some light on what jQuery is actually doing when you're using it!

Duncan Leung

Front End Developer at iHerb.com

Irvine, CA

Subscribe to Duncan Leung: Javascript and Front End Development

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!