Home > jquery > 10 Things I Learned from the jQuery Source

10 Things I Learned from the jQuery Source

June 14th, 2010

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

2010.07.21: jQuery Deconstructed is a rather nice way to look through the source. Also, the jQuery Source Viewer.

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.

jquery

  1. June 14th, 2010 at 13:19 #1

    I think I had one faux pas in here where I say

    $(elem).delay(4000).fadeOut();

    won't work. It will. But a non-fx queued event such as this won't work:

    $(elem).delay(4000).load('sweeturl.html');

    For that you'll need to dive into queue() and such.

  2. June 14th, 2010 at 13:39 #2

    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.

    $this.children('ul').fadeOut(1000).end().delay(500).queue(function(next){
    	$this.removeClass(className);
    	next();
    });
  3. June 14th, 2010 at 13:45 #3

    @Jeff L
    Perfect use case. Very nice Jeff.

  4. June 14th, 2010 at 14:46 #4

    Got this in blog bullet form somewhere?

  5. June 14th, 2010 at 15:03 #5

    that async recursion tip is sick! never knew about prefixing function with ! or + tho. i love "exotic" syntax. it's so magical.

  6. Tab Atkins
    June 14th, 2010 at 15:04 #6

    ;_; 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?

  7. June 14th, 2010 at 15:21 #7
    return 'jqueryscreencastsarethebest!!!!!LOL';

    I think you missed a few ‘1’s in between the exclamation marks. Otherwise, great screencast!

  8. June 14th, 2010 at 15:25 #8

    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.

    ~function x(){return;}();
  9. Chris
    June 14th, 2010 at 15:38 #9

    Did you get a haircut half way through this, Paul?

  10. June 14th, 2010 at 15:44 #10

    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

  11. Arian
    June 14th, 2010 at 15:59 #11

    You've talked about recursive periodicals, but how do you stop them, because you cannot use clearInterval anymore?

  12. Jared Roberts
    June 14th, 2010 at 16:00 #12

    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 …"

  13. Axium
    June 14th, 2010 at 16:02 #13

    In general, do you think people use $.support instead of $.browser?

  14. June 14th, 2010 at 16:30 #14

    @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

  15. Joe666
    June 14th, 2010 at 16:53 #15

    Simply awesome, Learned a lot with this, Thank you very much.

  16. June 14th, 2010 at 17:05 #16

    I totally enjoyed your screencast. Useful stuff and I love your humor :D :D Thanks!

  17. Will
    June 14th, 2010 at 17:43 #17

    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.

  18. Marcus Tucker
    June 14th, 2010 at 18:13 #18

    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? ;)

  19. June 14th, 2010 at 18:21 #19

    @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

  20. Kurt
    June 14th, 2010 at 19:03 #20

    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.

  21. Axium
    June 14th, 2010 at 19:14 #21

    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?

  22. June 14th, 2010 at 20:47 #22

    @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.

  23. June 14th, 2010 at 22:44 #23

    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

  24. June 15th, 2010 at 03:09 #25

    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…

  25. June 15th, 2010 at 03:21 #26

    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?

  26. June 15th, 2010 at 04:15 #27

    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.

  27. redsquare
    June 15th, 2010 at 04:17 #28

    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

  28. Justin Belcher
    June 15th, 2010 at 08:51 #29

    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?

  29. June 15th, 2010 at 10:02 #30

    @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.

  30. Ruslan Savenok
    June 15th, 2010 at 13:41 #31

    Please add download link for this video

  31. June 15th, 2010 at 15:58 #32

    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!

  32. June 16th, 2010 at 03:35 #33

    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"?

  33. June 16th, 2010 at 04:01 #34

    @Tom Bigelajzen
    oh, I haven't read your slides…
    nm, I'm smarter now.

  34. June 16th, 2010 at 06:31 #35

    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 :)

  35. June 16th, 2010 at 12:51 #36
  36. June 21st, 2010 at 16:24 #37

    Paul! You're my new idol :D

  37. June 24th, 2010 at 19:46 #38

    This is probably the best hour I've spent all week, thank you.

  38. July 2nd, 2010 at 03:38 #39

    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

  39. July 2nd, 2010 at 18:53 #40

    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?

  40. July 2nd, 2010 at 20:16 #41

    @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.

  41. July 6th, 2010 at 13:26 #42

    Thanks for the precise answer!

  42. jAndy
    July 9th, 2010 at 04:02 #43

    Wooh, nice one but I found a hiddenhancement!
    Within your getScript(), you declared "times" as global, by intentionally replacing the "," with a ";"! Sneaky!

  43. July 14th, 2010 at 11:58 #44

    Awesome video Paul. Are the slides available anywhere for the original talk? Thanks!

  44. Bob
    July 16th, 2010 at 19:52 #45

    hi, what textmate theme did you use?

  45. July 17th, 2010 at 05:06 #46

    Wonderful effect.

  46. July 17th, 2010 at 19:03 #47

    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 :)

  47. July 18th, 2010 at 08:59 #48

    sick! thanks for taking the time to bust out with the knowledge.

  48. July 18th, 2010 at 16:16 #49

    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.

  49. July 19th, 2010 at 19:34 #50

    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.

  50. July 20th, 2010 at 14:34 #51

    @Adam Eivy
    new Function(string) actually does create a closure just like function() {}, so it doesn't have any advantages over eval.

  51. July 21st, 2010 at 09:43 #52

    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 :)

  52. July 21st, 2010 at 10:35 #53

    @Dave Stewart
    I love this resource. Nice job on it. :)

  53. July 22nd, 2010 at 06:49 #54

    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 ;)

  54. July 23rd, 2010 at 04:11 #55

    @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.

  55. July 25th, 2010 at 06:16 #56

    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!

  56. Chris
    July 26th, 2010 at 07:30 #57

    Hey Paul,

    Excellent video, i was wondering which editor are you using in that presentation ?

    Cheers,

  57. July 26th, 2010 at 20:26 #58

    @Michael Geary, Campbell, CA
    Ah, thats kinda wacky. Oh well, thanks for the info.

  58. Apin Pratap
    July 28th, 2010 at 01:28 #59

    awesome video
    your presentation is really great
    Learned a lot of things, many thanks

  59. Waleed
    August 2nd, 2010 at 04:53 #60

    Thanks for sharing your knowledge, god bless you.

  60. August 5th, 2010 at 08:23 #61
  61. Paul Harrington
    August 8th, 2010 at 14:59 #62

    @Paul Harrington
    Whoops, this is lies.

  62. Daniel
    August 15th, 2010 at 20:45 #63

    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).

  63. August 16th, 2010 at 02:05 #64

    @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.

  64. August 16th, 2010 at 18:41 #65

    Awesome Video thanks! Can I ask which font you are using?

  65. Superficial
    September 6th, 2010 at 13:24 #66

    Great watch!
    Very funny to see you make more sense drunk than me when i'm sober! ;)

  66. September 18th, 2010 at 01:18 #67

    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

  67. September 19th, 2010 at 02:02 #68

    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!

  68. dev
    October 10th, 2010 at 13:20 #69

    it will be better if got subtitle , i somewhat not understand few part that u try to deliver.

  69. October 11th, 2010 at 07:08 #70

    Great intro to the jQuery source! Thank you for sharing this, that is like a make && make install =)

  70. TJ VanToll
    October 17th, 2010 at 21:48 #71

    Thanks for the video, I learned quite a bit.

  71. October 19th, 2010 at 07:44 #72

    PLEAS! someone tell me how to do the background on http://paulirish.com! that mistify stuff :)
    please answer per email to bb@icc.at

  72. Dave
    October 28th, 2010 at 19:12 #73

    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!

  73. October 28th, 2010 at 19:33 #74

    @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.

  74. Marcel Korpel
    October 31st, 2010 at 11:50 #75

    @Paul Irish
    A typical example for testing IE version is to check if I have to attach mouseover and mouseout event listeners to non-a elements (where :hover is 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.

  75. October 31st, 2010 at 13:25 #76

    @Marcel Korpel
    Marcel, those are two good examples.. I don't know of a feature detect for 'em

  76. November 4th, 2010 at 12:20 #77

    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/

  77. November 6th, 2010 at 22:00 #78

    Well… you caught me, I said 18 for the cornify part…

  78. Cogito
    January 2nd, 2011 at 09:36 #79

    This was awesome, Paul. Cheers!

  79. January 16th, 2011 at 17:08 #80

    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!

  80. Knu
  81. Renu Varghese
    January 25th, 2011 at 01:21 #82

    really so nice and simple code i got from here. Thanking you :)

  82. January 26th, 2011 at 08:10 #83

    Dude… that was one of the best javascript presentations I've ever seen. Thanks man!

  83. February 1st, 2011 at 10:58 #84

    Veeery instructive as well as entertaining. Thanks, I learned some awesome stuff here!

  84. February 13th, 2011 at 17:27 #85

    wicked cool screencast. thanks for taking the time to produce it. best use of an hour all weekend!

  85. February 13th, 2011 at 23:22 #86

    @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

  86. Nick Ryan
    March 16th, 2011 at 03:52 #87

    Great video. I like the way you overrode JQuery functionality without hacking your local copy.

  87. March 30th, 2011 at 19:14 #88

    Did you have the video of that conference?
    And it would be very nice of you to send me one copy.
    Thank you !

  88. Nicholas Johnson
    April 5th, 2011 at 04:07 #89

    You know that feeling of utter joy? I've had that twice already and I'm still only 17 minutes in :)

  89. DaveDisaster
    April 6th, 2011 at 05:24 #90

    I set up a test of the autofiring recursive function – the timing seemed off to me, so I threw in a 'stopwatch' to check.

    var start = new Date().getTime();
    testObj = document.getElementById('ickletest');
    testObj.style.left = '0px';
     
    function move(){
    	testObj.style.left = parseInt(testObj.style.left)+10+'px';
     
    	var elapsed = new Date().getTime() - start;
    	console.log('move: ' + elapsed);
    }
    function doStuff(){
    	setTimeout(move(),1000);;
    }
     
    (function(){
     
    	doStuff();
     
    	setTimeout(arguments.callee,1500)
     
    	var elapsed = new Date().getTime() - start;
    	console.log('loop: ' + elapsed);
    })()

    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

  90. May 18th, 2011 at 18:19 #91

    @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

  91. July 21st, 2011 at 05:28 #92

    This video makes me happy… in the pants

  92. August 1st, 2011 at 14:34 #93

    I've had that twice already and I'm still only 17 minutes in

  93. John
    August 27th, 2011 at 15:47 #94

    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.

  94. September 6th, 2011 at 19:41 #95

    Thanks, Paul! Loved it… Are you going to be at jQuery Boston 2011?

  95. May 12th, 2012 at 09:03 #96

    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?

  96. May 19th, 2012 at 10:51 #97

    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.

For code blocks, use <pre lang="javascript">. css and html4strict are also accepted.