I watched these videos on 2012/12/14. Today's jQuery version is 1.8.3. So there might be some differences from the original video. I've briefly noted some of the differences between what described in the video and the current stable release. Most code he desribed can be found easily in speed/jquery-basic.js
(1.4.2).
- 10 Things I Learned from the jQuery Source - YouTube
- 10 Things I Learned from the jQuery Source « Paul Irish
2010-06-14 (jQuery 1.4.1)
window
object passed into anonymous function, for faster object accessing.
undefined
as last parameter, to restore the potential overriden undefined
object (e.g. undefined=true
"a**hole effect").
(function(window, undefined) {
// do stuff here
})(window);
setInterval
may not work at the time you expected, when the action takes longer than the time you specified.
(function() {
doStuff();
// gonna wait doStuff done then
setTimeout(arguments.callee, 100);
})();
arguments.callee
deprecated in ES5 strict mode.
We can use named function:
(function loopback() {
doStuff();
// gonna wait doStuff done then
setTimeout(loopback, 100);
})();
(didn't get it)
This is a bridge for class
(DOM: className
) and for
(DOM: htmlFor
), and some downcased-to-camelCase mappings (!)
jQuery.props.dt = "data-type";
$("#something").attr("dt"); // gets its data-type attribute
"Constant" variable to define animation speed (e.g. fast
/ slow
). jQuery searches values in this object. If not found, it uses _default
value.
jQuery.fx.speeds.kilo = 1024; // define a new speed with 1024ms duration
$("#somethings").fadeIn("kilo");
In jQuery 1.4.x, DOM Ready callback is implemented in jQuery.bindReady
. However this function does not exist in 1.8.3 (current stable release). The most similar function is jQuery.ready.promise
.
Implemenation details:
- If
DOMContentLoaded
event is supported, use it. - If
document.attachEvent
exists (old IEs), use it to listen toonreadystatechange
event - Otherwise, use
doScrollCheck
, keeps trying scrolling the document (1ms), until it does not raise exception, then it's ready.
See also:
- IEContentLoaded - An alternative for DOMContenloaded on Internet Explorer
- src/core.js#L828 (jQuery.ready.promise)
Outdated. He extracted $.getScript
implementation of jQuery 1.4.1. Today's jQuery uses XMLHttpRequest.
The 1.4.x implementation can be found at speed/jquery-basic.js#L5060
(may be outdated. See sizzle.js
)
In 1.4.x,
$("#id").find("tag.thing")
is faster than
$("#id tag.thing")
because the latter must traverse the tree in JavaScript level instead of DOM level.
Todays' jQuery is Sizzle-driven and may already utilies this shortcut too.
:password
is slower than input:password
, because the former does traverse through all the possible tags.
jQuery use native parser (window.JSON.parse
) if supported.
Otherwise, make a new function and invoke it:
(new Function("return "+ jsonSrc ))();
Note the capital F
(not function
): it makes a new function
object, with source code in the parameter.
Since JSON is the literal representation of a JavaScript Object, the browser can parse the object literal inside the function, and turns it into a real object.
jQuery will check if the string is a real JSON string, otherwise it prints an error message to the console.
See also:
It uses Sizzle.uniqueSort
(same as today's implementation in 1.8.3).
The official document says that it does work for any array element other than DOM Element. It is still documented as "unspported" in today's 1.8.3.
Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers.
However I've tried non-DOM element scalars in 1.8.3, and it does work for Number, String and true
, but not work for null
, false
and undefined
. Objects (non-scalar) with same properties are all kept, duplications are not removed. Though this behavior makes sense, because two individual objects are compared by object address, not its properties.
[tl;dr] $.unique
doesn't guarantee correct result if there are items not DOM Element. So do use it for an array containing DOM elements only.
DOM elements:
div = document.createElement("div");
div.innerHTML = '<span class="a"></span><span class="b"></span><span class="c">'
"<span class="a"></span><span class="b"></span><span class="c">"
ar1 = $(div).find("span").get();
//=> [<span class="a"></span><span class="b"></span>,<span class="c"></span>]
ar1.concat($(div).find("span").get());
//=> [<span class="a"></span><span class="b"></span>,<span class="c"></span>,<span class="a"></span><span class="b"></span>,<span class="c"></span>]
jQuery.unique(ar1)
//=> [<span class="a"></span><span class="b"></span>,<span class="c"></span>]
Now let's see scalar values:
var arr;
// Number, true, String works
arr = [1, 2, true, "hi", 3, 3, true, 2, 1, "hi"];
$.unique(arr);
// => [3, "hi", true, 2, 1]
// false and undefined doesn't work
arr = [false, false, undefined, undefined];
$.unique(arr);
// => [false, false, undefined, undefined]
// null doesn't work, and will raise exception if the array contains anything other than null:
arr = [null, null];
$.unique(arr);
// => [null, null]
arr = [null, null, false];
$.unique(arr);
// => TypeError: Cannot read property 'compareDocumentPosition' of null
// Object literals doens't work either, since they're allocated in different memory spaces
arr = [{a:1, b:2}, {a:1, b:2}];
JSON.stringify($.unique(arr));
// => "[{"a":1,"b":2},{"a":1,"b":2}]"
Paul Irish hacked it to make 1.4.1's unique()
possible to also deal with non-DOM Element objects, see: How to fulfill your own feature request -or- Duck Punching with jQuery! « Paul Irish
See also:
In 1.4.1, to delay an animation from starting, this:
$(elem).delay(2000).fadeOut();
doesn't work because there is no queue, which delay
requires.
$(elem).queue(function() {
$(elem).delay(2000).fadeOut();
});
this would work.
I've tried 1.8.3 and it works without .queue
wrapping.
jQuery is constructed with many modules. We can build a jQuery with a small set of modules included. The jQuery team said in mid-2012 that there will be a jQuery build tool. It's been 2 years since Paul Irish's cast.
Nowadays people use jQuery from public CDNs. I think building my own jQuery and deliver it from my server means I cannot leverage public caching for jQuery JavaScript file, and pay delivering fee for it.
- 11 More Things I Learned from the jQuery Source - YouTube
- 11 More Things I Learned from the jQuery Source « Paul Irish
2011/01/19
It initializes in a local variable and then assign back to window.jQuery
.
(I didn't get it.)
<div data-awesome="true"></div>
<div data-someobj='{ "best": "jQuery"}'></div>
In the source code it uses ?:
conditional tree (bad-smell) to see if the string equals to true
, false
or null
literals and return directly. If none matched, it tries to parse it as JSON. If JSON parsing failed, it returns the original string.
IE detection -- Inserts <!--[if IE x]><i></i></![endif]-->
into a div, and test if a specifc i tag exist.
This is not how jQuery detects IE, Paul Irish just mentioned a technique used in it.
div.getElementsByTagName('i')
It actually is a NodeList, and updates lively as div
element changes.
E.g.:
var ul = document.createElement("ul");
var items = div.getElementsByTagName("li");
ul.innerHTML += "<li>1</li>";
console.log(items); //=> [<li>1</li>]
ul.innerHTML += "<li>2</li>";
console.log(items); //=> [<li>1</li>,<li>2</li>]
Also applies to getElementsByClassName
, but does not apply to querySelectorAll
.
When getting or setting CSS properties that are unsupported in the browser (e.g. opacity
in IE6 or backgroundPositionY
in Firefox), jQuery will fallback to browser-specific method according to cssHooks
functions.
See also:
(I rarely use .css
because I usually achieve it by Compass and alternating element's className
to change the layout.)
jQuery.fn = jQuery.prototype;
This is why we can define a new plug-in by
jQuery.fn.myPlugin = function() {};
See also:
Ace writeup. :D