How jQuery Works

How jQuery Works

jQuery isn't magic. It's Javascript.

Published:

Many developers who are just getting started with front-end coding come across jQuery and think it is some kind of miraculous super-language, but the truth is jQuery isn't magic. It's JavaScript.

The mysterious $

If you are a Javascript beginner, it may not initially be obvious that the jQuery $ is nothing more than a variable definition. In other words, this is completely valid Javascript:

var $ = {};

The actual jQuery source code for implementing the $ syntax looks like this:

window.jQuery = window.$ = jQuery;

This takes the locally defined variable jQuery and attaches it to the global window variable, allowing you to access jQuery using either the $() or jQuery() syntax.

The point is, there is nothing special about the $. It is just a normal variable name.

jQuery​.Method()​.Chaining()

jQuery includes a convenient feature that allows you to call multiple methods in a single expression. This is called method chaining, and it looks something like this:

$("#myDiv").css("color", "#F00").html("some text");

As you can see, this sets the font color and creates the HTML content all in one expression. Generally, this is fairly simple to implement. You simply put all your chainable methods in the same object, and have them return this.

var myObject = { methodOne: function () { console.log("method one"); return this; }, methodTwo: function () { console.log("method two"); return this; }, };

With this example, you could then write some code like this:

myObject.methodOne().methodTwo();

This is basically what jQuery does, except some of its methods aren't chainable all of the time. For instance, the html() method can be used to either set or get the HTML content. It only makes sense for the setter to be chainable, since the getter is expected to return a string, and not this.

jQuery has an access() method that is used to simplify this varying behavior. Here are the relevant parts of its implementation:

var access = (jQuery.access = function (elems, fn, key, value, chainable, emptyGet, raw) { // I have excluded the unrelated code in this function return chainable ? elems : // Gets bulk ? fn.call(elems) : length ? fn(elems[0], key) : emptyGet; });

Note the 5th parameter in this method. As the name implies, this determines if the method will be chainable or not. When the chainable parameter is truthy, it will return the elems parameter, which should be the jQuery object that originally made the call.

If the parameter is falsy, it will instead return the return value of the fn function.

So, to continue with the html() method as an example, here is how it uses the access() method.

html: function( value ) { return access( this, function( value ) { // this function is the actual html() implementation }, null, value, arguments.length ); }

this is passed as the elems parameter. Remember, elems is the parameter that will eventually be returned if chainable is truthy.

arguments.length is passed as the chainable parameter in the access() method. This works because the getter version of html() has no parameters, so arguments.length will be 0, which is considered falsy.

The setter uses a single string parameter, so arguments.length will be 1 and truthy.

jQuery.fn.WHAT?!?

If you have been using jQuery for while, you have probably needed to use a jQuery plugin at some point. If you have ever looked at the source code of a plugin, you will have seen something like this:

$.fn.myPluginName = function(){ ... };

But how exactly does .fn work? It is nothing more than a reference to the jQuery object's prototype. That's it.

This is the code used to implement jQuery.fn:

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

I assume this is meant to reduce verbosity, but it is also rather confusing. It works just as well to define your jQuery plugins like this:

$.prototype.myPluginName = function(){ ... };

So what is the jQuery object anyway?

The jQuery object is a little crazy, so I'm going to step through the source code and explain how it all fits together.

If you remember from my earlier explanation, window.$ references a local jQuery variable. This is the definition of that variable:

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

So, when you call $('div');, this is used to create an instance of jQuery.prototype.init (remember, fn is the same as prototype).

The init function itself isn't particularly interesting. It basically just does some cross-browser checks and creates an array of elements based on your selector parameter.

The init function's prototype is where things start to get a little insane. Note the comment in the code above that says:

The jQuery object is actually just the init constructor 'enhanced'

This is because the jQuery.fn.init function actually has the same prototype as the jQuery object:

init.prototype = jQuery.fn;

This allows the jQuery and init objects to both have access to the same methods, but also maintain other methods individually . For instance, $.ajax() makes sense on the global object, but $(‘#myDiv').ajax() does not.

Also, this enables more intuitive access to the prototype, so plugins can be created with:

$.fn.myPlugin = function(){ ... };

instead of

$.fn.init.prototype.myPlugin = function(){ ... };

But, if you happen to be a fan of verbosity, it could also be written like this:

jQuery.prototype.init.prototype.myPlugin = function(){ ... };

Want to know more?

If you really want to understand how jQuery works, you can read the source code:

Let me know what you think

I intend to write more "How It Works" articles, so if you have any suggestions for code you would like to see explained, let me know in the comments.

Hire Me

Looking for a React Native or Web Developer?

Hire me today!
© 2022 Travis Wimer