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.

Paul Irish jquery

  1. #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. #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. #3

    @Jeff L
    Perfect use case. Very nice Jeff.

  4. #4

    Got this in blog bullet form somewhere?

  5. #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
    #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. #7
    return 'jqueryscreencastsarethebest!!!!!LOL';

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

  8. #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
    #9

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

  10. #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
    #11

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

  12. Jared Roberts
    #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
    #13

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

  14. #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
    #15

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

  16. #16

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

  17. Will
    #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
    #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. #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
    #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
    #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. #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. #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. #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. #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. #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
    #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
    #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. #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
    #31

    Please add download link for this video

  31. #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. #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. #34

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

  34. #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. #37

    Paul! You're my new idol :D

  36. #38

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

  37. #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

  38. #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?

  39. #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.

  40. #42

    Thanks for the precise answer!

  41. jAndy
    #43

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

  42. #44

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

  43. Bob
    #45

    hi, what textmate theme did you use?

  44. #46

    Wonderful effect.

  45. #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 :)

  46. #48

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

  47. #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.

  48. #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.

  49. #51

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

  50. #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 :)

  51. #53

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

  52. #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 ;)

  53. #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.

  54. #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!

  55. Chris
    #57

    Hey Paul,

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

    Cheers,

  56. #58

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

  57. Apin Pratap
    #59

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

  58. Waleed
    #60

    Thanks for sharing your knowledge, god bless you.

  59. Paul Harrington
    #62

    @Paul Harrington
    Whoops, this is lies.

  60. Daniel
    #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).

  61. #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.

  62. #65

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

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

i left this space here for you to play. <3