10 Things I Learned from the jQuery Source
Last weekend was the incredible TXJS conference. It was a grand time in hot hot Texas. Joe Bartlett has a great conference roundup, rebecca's pix are quite pretty, and most of the speaker slides are on the official site.
I've rerecorded my talk in screencast form. Here's what to expect from the 52 minute video:
It’s jQuery on the big screen. We’ll open the jQuery source and run through how the jQuery object works, covering self-executing anonymous functions as a global abatement technique, several interesting jQuery methods, internal jQuery paradigms, and hiddenhancements. You’ll learn JavaScript techniques you can apply to your own code, as well as the basic workings of jQuery itself.
Enjoy. Please comment if you have a question or if I messed something up. :)
youtube hosted version here
Also, (you should already know this, but…) if you like this screencast you should subscribe to the yayQuery Podcast. It's techy but entertaining and there will be smiles.
I think I had one faux pas in here where I say
won't work. It will. But a non-fx queued event such as this won't work:
For that you'll need to dive into queue() and such.
I've used queue() for delaying a non animation method before. I wanted to fade a menu over a full second, and remove a class from the parent LI after half a second.
@Jeff L
Perfect use case. Very nice Jeff.
Got this in blog bullet form somewhere?
that async recursion tip is sick! never knew about prefixing function with ! or + tho. i love "exotic" syntax. it's so magical.
;_; Vimeo regularly craps out on me on Linux, and this one is no exception. Any chance you could get this up on Youtube where I can use the player instead?
I think you missed a few ‘1’s in between the exclamation marks. Otherwise, great screencast!
this works too. i wonder what the real advantage to this is other than one less char — if you don't care what the returned value is.
Did you get a haircut half way through this, Paul?
Hey Paul!
I've just seen this screencast (nettuts+ ;)) and am totally amazed. I wish my profs could explain like you do!
The only thing I miss here: I can't really find a) the code b) the slides of your talk…
–
Asmodiel
You've talked about recursive periodicals, but how do you stop them, because you cannot use clearInterval anymore?
doScrollCheck segment made me last my ass off.
"… immediately we're like, whatever dude, do it all over again. go back go back, 1 millisecond. it like no no no. and then finally at some point doScroll is not gonna raise an exception and then ah yeah we're good …"
In general, do you think people use $.support instead of $.browser?
@Tab Atkins
Youtube version is on the way.
@Chris Hahah yes i totally got a haircut about 20mins in. :)
@Asmodiel Here is the source with a buncha leftover coding: http://gist.github.com/438326
@Arian Well you are explicitly calling the function over again. So you make some conditional if statement to make sure you're only recursing if you want to.. Otherwise you can return or do nothing to stop repeating.
@Axium Depends for what. Some things you cant test for. But most things you can.. For those you should use what's in $.support.. write your own support tests and add them to $.support or just test each time. If you have a good example of what you typically use $.browser for I can offer a way to do it better. Also check the docs for jQuery.support
Simply awesome, Learned a lot with this, Thank you very much.
I totally enjoyed your screencast. Useful stuff and I love your humor :D :D Thanks!
Are there any stack-overflow concerns (An actual stack-overflow, not stackoverflow.com) when calling a function recursively every 100 milliseconds via setTimeout? I always figured setInterval was better.
Cool screencast, thanks!
I have a few questions:
1) Surely having a short (1ms) timeout in doScrollCheck places quite a load on the CPU and might actually slow down the DOM processing? Why not a longer value like 5ms? (I suspect that the answer may simply be that using the function is an edge case for <=IE6 anyway so nobody cares, but I thought I'd ask)
2) RE animation jerkiness hack for IE: I don't see how/why increasing the duration helps, that just means that the animation has to calculate twice as many frames over twice the time, which is still the same frame rate and thus CPU load. It's the kind of time regulation hack that old school games programmers used for the IBM PC 286 that then broke spectacularly when 386s came out and ran everything so much faster! Surely it would be much better to automatically throttle the animation FPS (i.e. alter the interval) depending on the time taken to render the previous frame, which would also be completely browser & CPU independent (i.e. scaling automatically)?
3) Were you a little drunk when you recorded this screencast, or just very tired? ;)
@Tab Atkins Youtube version added. Check above.
@Will Nope. Someone yell at me if I'm wrong but with neither will you run into a stack overflow or recursion problem. They kinda kick each invokation into a pseudo-thread. Sorta kinda.
@Marcus Tucker Check out John Resig's timer research and you'll find IE's absolute minimum is somewhere around 13-17ms. So 1 is just for fun; plus it saves a byte!
2) Because of the way animations are done in jQuery it's not really practical to specify by frames (although many YUI folks would agree that's a smart solution). But all I can say is the duration change *does* help.
3) Sorta yup. :p
You blew my mind. I did not even think my brain had capacity for this much new knowledge. Thanks a lot. I also have to second korbsan – I loved your humor throughout the presentation; it made it a pleasure to follow along.
Sorry that should have read "do you think people should use $.support instead of $.browser?" I think your use case in the video is one I find myself needing a lot–IE<8. Could that easily be targeted with $.support?
@Axium
Well… the usecase in the video was very performance related. And that's something a benchmark is best at. Unfortunately… benchmarks take time to be accurate so it's not suitable for a feature test like thing (unless it had been done lazily then cached)..
But like all the documentation says… avoid using $.browser if you can.
Hey Paul,
Would appreciate if you can post a brief list of the 10 topics some where,
so pros can just scan through if you have touched any new patterns.
Would be hard to watch the entire video and be disappointed to see nothing
@Pari Nannapaneni
Here's a summary: http://www.davetech.com/blog/paul_irishs_jquery_craziness
Great screencast, very useful, congratulations!
I always wanted to dig into the jQuery code, but couldn't find the time / courage to do so.
Loved the async recursion pattern – now I have a name for it!
Duck punching – ruby folks (and probably others) call it monkey patching.
Very cool JSON evaluation with the Function constructor!
Thought $.browser was deprecated in favor of support…
One other thing: I suspect that shortening the jQuery lib by cutting on the dependency direction will not work because there is no way you can tell the dependencies are not a graph instead of a tree – unless that was a conscious decision of jQuery contributors.
You can try it, but you can only be sure it does not break in call-time, not in eval-time…I think…
… or am I missing something here?
Watched all of it! Thanks for the screencast, now I won't be afraid to dig deeper into jQuery.
BTW: Whats your setup for making the screen cast? The experience was great.
Very useful Paul, if only every 50 minutes could be as productive as this.
Changing a good few of my setIntervals as we speak!
Cheers fella
Killer talk man—I picked up a lot of cool stuff.
You mentioned ECMA 5 strict and that made me wonder about your approach to code QA. Do you try to code to strict? Do you make use of JSLint? Or do you mainly approach QA with unit tests?
@Pedro Yes definitely use feature detection (or bug detection) where possible instead of support. My usecase here was performance related and that's much tougher to determine on the fly. But you're absolutely right.
I have some friends working on a modular build of jQuery but it does seem to be a bit innerconnected, it's true. All I can say is that the jQuery test suite is NOT a fan of removing modules. :)
@zaf Screenflow, a haircut and a can of PBR.
@redsquare Thanks Red! :)
@Justin Belcher I only go to JSLint when I have an error that's confusing me (same with html validation). I try to code strict when I remember the stricty things to do, but I'm not going as far as to do a
'use strict';in my code. (Definitely don't do that if you're not actually testing it against strict mode.) Unit tests catch so many damn bugs. Every time I start using it on a project I'm impressed at all the shame the tests save me from possibly putting out buggy code.If you have a build system, running your code through closure compiler or YUI Min will also catch some weird bugs from time to time.
Please add download link for this video
Ok, so this was the most informative and entertaining jQuery screencast ever. Not sure if you've done these before, but I sure hope they continue!! Thanks for sharing the knowledge!
Great screencast.
I was wandering, when you talked about selector performance you compared
$('#id some.tag') to $('#id').find('some.tag')
I on the other hand normally use $('some.tag', '#id'), is it like using "find"?
@Tom Bigelajzen
oh, I haven't read your slides…
nm, I'm smarter now.
Awesome screencast. I especially dig the alternative
x = (new Function('return '+data))();
as opposed to
eval('('+data+')');
It's nice to know there's a better alternative to parsing JSON–and that now I can just use jQuery :)
Now I'm going to dig a lot more into the jQuery source, which I had been ignoring before :)
@Ruslan Savenok on the vimeo page if you login you can download the original. http://vimeo.com/12529436
@Tom Bigelajzen I answered this exact thing over here: http://net.tutsplus.com/tutorials/javascript-ajax/10-things-i-learned-from-the-jquery-source/comment-page-1/#comment-302833 :)
Paul! You're my new idol :D
This is probably the best hour I've spent all week, thank you.
Beautiful, I got my hands dirty with jQuery about a year ago. I was making a mozilla plugin but wanted some of the cool jQuery features and while I was trying to get the two to work together I ended up running into the oddities you explained. Now I make it a point to view the source throughly if i use it often, you never know what goodies you will find. The 10 minutes you spend could save you 2 hours of trouble shooting in the future.
Thanks again, Paul
Hey Paul, big fan.
I ran a practical test and found that $('#id tag.class') actually runs faster than $('#id').find('tag.class'). Here's the link:
http://jsfiddle.net/jsKtU/
(will need to open Firebug console or Inspect Element console to see results)
Can you explain if I'm understanding something wrong?
@Mike
Yay for testing! :)
In browsers with querySelectorAll it doesnt really make too much of a difference (but yah.. your numbers dont lie), but ones without (IE6 and IE7) you should see things with .find() as much faster.
Thanks for the precise answer!
Wooh, nice one but I found a hiddenhancement!
Within your getScript(), you declared "times" as global, by intentionally replacing the "," with a ";"! Sneaky!
Awesome video Paul. Are the slides available anywhere for the original talk? Thanks!
hi, what textmate theme did you use?
Wonderful effect.
Thanks @paulirish i am tired but i really enjoyed it. i love the undefined part :P i am waiting for another video exploring more jquery source. reading code is dry, watching video is good :)
sick! thanks for taking the time to bust out with the knowledge.
In the first part about anonymous functions, you said that (function () { })() would be the same as function () { }()
Maybe I'm missing something but I just put document.write("I'm anonymous!"); inside and if you leave the parenthesis off of the front of the function () it will not work but once I add the parenthesis it goes off without a hitch.
That was brilliant, and I will totally make little explosion noises when ever I delete code from now on. And the lasers when finishing blocks. Awesome.
@Adam Eivy
new Function(string) actually does create a closure just like function() {}, so it doesn't have any advantages over eval.
Great video, and interesting points.
Not sure if you've seen, as it seems to have been picked up by a load of blogs in next to no time, but I released this a couple of days ago:
http://www.keyframesandcode.com/resources/javascript/jQuery/deconstructed/
It's an interactive, visual breakdown of the code, with heavy hyperlinking and some other nice featurettes.
Enjoy :)
@Dave Stewart
I love this resource. Nice job on it. :)
Glad to contribute :)
Not sure if you got my mail about Array-like objects, but I think I'm going to be going the Prototype JS Lib way and extending an Array for my Collections objects. That also allows me to subclass any Collections superclass as well, so it's perfect for me.
As I'll be digging around the Prototype library, I'll most likely do a Prototype Deconstructed as well. Hell… why stop there!? MooTools, watch out ;)
@Paul Harrington
The advantage of new Function instead of eval is that it is *much* faster on a large JSON object when Firebug is running. For some reason Firebug causes eval to run much slower, but it doesn't affect the speed of new Function.
I am not a programmer and I have been never dunked into jquery, but your screencast makes me very curious. So you did a great job when somebody watches 53 minutes of something he understood as good as nothing ;)
Thank you!
Hey Paul,
Excellent video, i was wondering which editor are you using in that presentation ?
Cheers,
@Michael Geary, Campbell, CA
Ah, thats kinda wacky. Oh well, thanks for the info.
awesome video
your presentation is really great
Learned a lot of things, many thanks
Thanks for sharing your knowledge, god bless you.
baidu
@Paul Harrington
Whoops, this is lies.
Great video. Two quick comments:
1. I tried to write an anonymous self-executing function without parentheses surrounding the function and Firefox, Safari, Opera and Chrome (not tested in IE) all gave a syntax error. Am I missing something?
2. You mentioned that the _jQuery and _$ are local variables, but if a variable is defined without using 'var' it is defined on global object (window).
@Daniel
1. Yeah I had confused it with
var x = function(){ … }(); which DOES work. Somehow assignment makes it legit. My bad.
2. correct. _jQuery and _$ are defined in a big var x, y, z; comma chain.
Awesome Video thanks! Can I ask which font you are using?
Great watch!
Very funny to see you make more sense drunk than me when i'm sober! ;)
var myArray = [5,2,10,4];
var randomValue= myArray[Math.floor(Math.random()*times.length)];
really really interesting way of getting a random element in your array. awesome
Great presentation. As someone fluent in MooTools who's only bothered to look under the hood of jQuery once or twice, I totally appreciate the way you revealed some of the subtle tricks and conventions.
Also, way to make the experience of staring at someone else's screen full of code for nearly an hour surprisingly interesting and enjoyable!
it will be better if got subtitle , i somewhat not understand few part that u try to deliver.
Great intro to the jQuery source! Thank you for sharing this, that is like a make && make install =)
Thanks for the video, I learned quite a bit.
PLEAS! someone tell me how to do the background on http://paulirish.com! that mistify stuff :)
please answer per email to bb@icc.at
Hi
Thanks for the great talk.
This might be a dumb question but, re. the example getScript() function:
would it be safer to set/assign the script element's onload handler *before* setting its src attribute?
I mean, obviously it works as-is (although I don't get how!)
Thanks for any thoughts!
@Dave
Because at that point the script node isnt in the DOM, there wouldn't be a race condition…
but generally yes that is always a good rule to abide by.
@Paul Irish
A typical example for testing IE version is to check if I have to attach
mouseoverandmouseoutevent listeners to non-aelements (where:hoveris not supported in IE 6). Another use is to check whether I need to use a special filter to display alpha-transparent PNGs in IE < 7 or not.I'm curious if you know a way of feature detection to circumvent these quirks.
@Marcel Korpel
Marcel, those are two good examples.. I don't know of a feature detect for 'em
This is a really great walkthrough of the jQuery source, highly recommended for anyone who wants to understand how things work rather than just having them happen. Paul is a great speaker too, so it is fun and enjoyable. He also walks through making a standalone script that can fetch another script that is fairly useful for bookmarklets and such…Since I took the time to type it from his screen I figure I will post it on my blog and link to it so no one else has to waste the time re-typing it. http://www.blog.cordslatton.com/2010/11/investigating-the-jquery-source/
Well… you caught me, I said 18 for the cornify part…
This was awesome, Paul. Cheers!
Thanks for the presentation, but the video is just too long.
Is there a set of slides or just text version with main points outlined?
Thanks!
@Paul Irish concerning undefined you should read this
http://whereswalden.com/2010/01/12/more-es5-backwards-incompatible-changes-the-global-properties-undefined-nan-and-infinity-are-now-immutable/
really so nice and simple code i got from here. Thanking you :)
Dude… that was one of the best javascript presentations I've ever seen. Thanks man!
Veeery instructive as well as entertaining. Thanks, I learned some awesome stuff here!
wicked cool screencast. thanks for taking the time to produce it. best use of an hour all weekend!
@jason kuhn
The ~ before the function converts the fn from a function statement to a function expression
http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife
Great video. I like the way you overrode JQuery functionality without hacking your local copy.
Did you have the video of that conference?
And it would be very nice of you to send me one copy.
Thank you !
You know that feeling of utter joy? I've had that twice already and I'm still only 17 minutes in :)
I set up a test of the autofiring recursive function – the timing seemed off to me, so I threw in a 'stopwatch' to check.
Both console.logs repeatedly fire at the same time (give or take a millisec) at 1500ms intervals – I would have expected it to be a 2500ms loop with the logs firing at 1500 and 2500.
Am I being completely dense or is there a booboo somewhere?
Full test html: http://pastebin.com/qMGUrKuf
@DaveDisaster – Your problem is in your assumption that setTimeout is accurate. It's not. You cannot depend on setTimeout for real time-based execution. For that you must use other methods. Here is a related discussion from StackOverflow:
http://stackoverflow.com/questions/196027/is-there-a-more-accurate-way-to-create-a-javascript-timer-than-settimeout
This video makes me happy… in the pants
I've had that twice already and I'm still only 17 minutes in
I really wanted to see your presentation. But a black background with red, green,yellow text was not readable. At full screen it was blurry.
Sorry. I had to leave after a few minutes.
Thanks, Paul! Loved it… Are you going to be at jQuery Boston 2011?
Question about the "asynchronous recursion": isn't this creating infinitely deep stack traces? (since we're never leaving the current context frame when calling the function again) And would this potentially cause problems?
Interesting fact here: http://cl.ly/0Q1I410M1s0n2z383J2X
Only class and for are quoted because they are reserved words in JavaScript (even though class is useless right now and is reserved for a possible future use…)
My 2 cents.