
18 surprises when reading jQuery source code
- Transfer
Translation of “18 Surprises From Reading jQuery's Source Code” by David Aragon.
I love jQuery, and although I consider myself an advanced JavaScript developer, I have never, until now, read jQuery sources from beginning to end. Here are a few things I learned about this:
Note: I use the syntax
An earlier version of this article said that the return value of the argument function from Example 5 should be a comma-separated string. It turns out that this should be a string separated by spaces. Thanks Jonathan!
I love jQuery, and although I consider myself an advanced JavaScript developer, I have never, until now, read jQuery sources from beginning to end. Here are a few things I learned about this:
Note: I use the syntax
$.fn.method()
to specify a call method
on a selection of elements. For example, when I write $.fn.addClass
, it means use like $(‘div’).addClass(‘blue’)
or $(‘a.active’).addClass(‘in-use’)
. $.fn
This is a prototype for jQuery element wrappers.- Sizzle Weight: Sizzle is a jQuery engine for CSS selectors from the DOM. This is what turns
$(‘div.active’)
into an array of elements with which you can operate. I knew that Sizzle is a big part of jQuery, but I was surprised to find out how huge it really is. This is the biggest feature in terms of the number of lines in the jQuery source code. According to my estimates, it makes up 22% of the entire code base. This overshadows the next largest thing in jQuery -$.ajax
which takes up only 8% of the library code. - $ .grep: This method is similar to the Underscore method
_.filter
, it also takes two arguments, an array of elements and a function, and returns the elements that passed the function test. - Bubbling caveats: jQuery prevents bubbling of one type of event. This is an event
load
. Inside, jQuery passes a special flagnoBubble: true
for allload
events, so that image.load events cannot float up to the window object (which may be mistaken as window.load). - Default animation speed: jQuery animates elements by changing their styles in quick succession. Each of these quick changes is called a “tick.” The default speed for animation is a tick every 13 milliseconds, you can adjust this by overriding it
jQuery.fx.interval
with your own number. - $ .fn.addClass takes a function: We usually pass a string with class names to the $ .fn.addClass function. But she also accepts the function. The function passed must return a string with class names separated by a space. As a bonus, this function takes the index of an element from the list of elements to which it is applied, which allows you to build smart class names.
- $ .Fn.removeClass can do the same: This method also accepts a function, as in the method above. The function passed also takes the index of the element.
- Pseudo-selector: empty This handy pseudo-selector selects elements without child nodes.
- Pseudo-selectors: lt and: gt: These pseudo-selectors select items by their index in the selection. For example, it will
$(‘div:gt(2)’)
return all divs except the first three (indexing starts from zero). If you pass a negative number to the argument, jQuery will count back from the end of the selection. - $ (document) .ready () uses promises: It turns out that jQuery uses its own product. Inside, the good old
$(document).ready()
jQuery deferred is used to determine when the DOM is fully loaded. - $ .type: I'm sure you are all familiar with use
typeof
, but did you know that jQuery provides a method.type()
? The jQuery version is more reasonable than the native browser version. For example, ittypeof (new Number(3))
returns “object,” while it$.type(new Number(3))
returns “number.” Added: As ShirtlessKirk pointed out in the comments, $ .type returns the return type of the .valueOf () method. So it’s more correct to say that $ .type will tell you the return type of the object. - $ .fn.queue: You can get all element effects, using the following code:
$(‘div’).queue()
. This is useful if you need to know how many effects still need to be applied to an element. It’s even more useful to add effects to the queue yourself. From jQuery docks:$( document.body ).click(function() { $( "div" ) .show( "slow" ) .animate({ left: "+=200" }, 2000 ) .queue(function() { $( this ).addClass( "newcolor" ).dequeue(); }) .animate({ left: "-=200" }, 500 ) .queue(function() { $( this ).removeClass( "newcolor" ).dequeue(); }) .slideUp(); });
- Click events are forbidden on inactive (disabled) elements: jQuery does not process click events on disabled elements, a good optimization that removes the obligation to check this yourself.
- $ .fn.on accepts an object: Did you know that it
$.fn.on
accepts an object to connect to multiple events at once? Example from jQuery docks:$( "div.test" ).on({ click: function() { $( this ).toggleClass( "active" ); }, mouseenter: function() { $( this ).addClass( "inside" ); }, mouseleave: function() { $( this ).removeClass( "inside" ); } });
- $ .camelCase: This helper method turns hyphens into camelCase.
- $ .active: The call
$.active
returns the number of active XHR requests. This can be useful to limit the number of simultaneously active AJAX calls. - $ .fn.parentsUntil / $ .fn.nextUntil / $ .fn.prevUntil: I am very familiar with the methods
.parents()
,.next()
and.prev()
, but I was not aware of the existence of Until versions of these methods. Essentially, these methods will select the parents / next / prev elements until they reach the passed stop element. - Arguments $ .fn.clone: When you clone an element, you can also clone its data attributes and events by passing the
true
first argument to the methodclone
. - Other arguments to $ .fn.clone: In addition, you can clone data attributes and events of children by passing
true
in the second argument. This is called "deep cloning." The second argument defaults to the first (which, by default, is false). Thus, if the first argumenttrue
and you want the second to be equaltrue
, you can omit the second argument.
An earlier version of this article said that the return value of the argument function from Example 5 should be a comma-separated string. It turns out that this should be a string separated by spaces. Thanks Jonathan!