Prototype and jQuery

Since I discovered it a few years ago, I've been a big Prototype fan.  It's simple, and gets the job done with a minimum of fuss.  It's not without warts, of course.  I still occasionally forget to put 'new' in front of Ajax.Request, and some of the Ruby-like methods share their lineage's arcane naming.  When it was new, it was the best thing around, and while it now has competitors, it's certainly not lagging behind.

At work, however, jQuery has been adopted as the standard (and I've no power to change it).  The lack of the $() function is annoying; several times I've debated adding this function (or one of various similar ones) to our library:

function $(id) {
  return jQuery("#" + id)[0];
}

I haven't, of course, as it's not the jQuery way.  jQuery also lacks any sort of class assistance, so we still use the Prototype class framework for our class-based JS.  That seems to work fairly well, except for the fact that we have to use two frameworks where one could suffice.

jQuery is not without it's benefits, of course.  The plugin architecture is a nice aspect that Prototype didn't really offer an equivalent of.  It means the core stays lighter (good), but if you want additional functionality you're stuck managing files from a bunch of different projects (annoying).  Event handling is a bit more straightforward, in some ways.  "Magically" acting on collections of elements with a single call (i.e. no .each(function(o){…}) garbage) definitely makes for more readable code as well.

Because of this shift at work, I've been porting some of my personal apps over to jQuery as well.  I've actually been using a couple jQuery plugins (both self-written and external) for specific tasks for a while now, but not the core framework.  What I've found, however, is that jQuery can be prone to slow code.  To avoid a huge amount of extra work on the part of the JS interpreter, using temporary variables for jQuery objects is essential.  If you do strictly id-based queries, the degradation isn't huge, but if you do CSS-based queries, it can be significant.  With Prototype's focus on id-based queries (at least until $$() came about in 1.5), that was less of an issue.

This need to query a minimum number of times can provide a fair amount of complexity when you have more than a handful of closures hanging about and/or a dynamic DOM.  You end up doing a lot of state management work because you're, in effect, caching DOM lookups and have to ensure you never have stale cache.

Other than that issue and the lack of an equivalent to document.viewport, porting has been relatively painless.  Still very id heavy, so not leveraging jQuery as much as could be, but most of what I'm doing wouldn't benefit from other selectors.

Which one is better?  Hard to say.  jQuery seems to make you work harder to type less code, while Prototype seems to cost you a few more characters for a bit less density.  With the exception of Prototype's class support, their feature sets are fairly equivalent, especially with jQuery UI now available to "compete" with Scriptaculous.  For the moment, I'm choosing to use jQuery on new stuff, but wishing for Prototype every few minutes.  Until I come up against some sort of significant wall, it'll probably stay that way, just to stick with the same tooling professionally and personally.  And over time it'll probably get better as the Prototype-ness fades from apps.

9 responses to “Prototype and jQuery”

  1. John Whish

    I use jQuery a lot and refer to elements by id. I might be missing the point but doesn't this shorthand do what you want?

    $(function(){
    reference = $('#myelement');
    });

    as an id should be unique you don't need to reference the first element in the array.

  2. George Bridgeman

    "The lack of the $() function is annoying"

    There is a $ function in jQuery, which is just the same as the jQuery function. Not sure what would make you think the $ function didn't exist. I've been using it for months!

    There's a big advantage of jQuery over Prototype but it's very situational. If you're writing a JS library which uses jQuery, you obviously don't want to interfere with the $ (and perhaps jQuery) function if your client is using Prototype, another version of jQuery, or has their own implementation of either of these functions. jQuery provides the noConflict method which will let you put the $ function into your own variable and put whatever was in there originally, back in.

    Say a client is using the $ function Prototype, then I go include jQuery using my library. jQuery can put Prototype back into window.$ and return a reference to jQuery's $ function for you to put into your own variable for use internally by your own library. So instead of doing $('#theId'), you'd do jq('#theId'), for example.

    Like I said, it's very situational, but it's something jQuery has which Prototype doesn't (as far as I can tell so far).

    Hope this makes sense!

    George.

  3. Brian Swartzfager

    You can use '$("#elementId")' instead of 'jQuery("#elementId")' in your jQuery functions by default so long as that doesn't cause a conflict with another JavaScript library you're using–see Using jQuery with Other Libraries.

    You mentioned that you're still using the Prototype class framework in conjunction with jQuery, so that's why you may need to use the more verbose jQuery call.

  4. Dan G. Switzer, II

    $() is already a shortcut for jQuery(), but as you mention some people miss the $() = DOM object so you might want to do this instead:

    function $$(id){ return jQuery("#"+id)[0]; }

    Personally, I rarely deal with raw DOM elements anymore. Also, we'll getting used to the CSS-style selectors was something I wasn't fond of at first (since I thought have to write "#id" was a bit of a PITA,) I've since come to like it. I find it makes switching between writing CSS rules and jQuery much easier and it's more clear.

  5. Josh Nathanson

    What's nice about $() returning jQuery rather than a DOM node, is that you can then chain methods like so:
    $("Hello").appendTo("body").css("background-color","red");

    Maybe Prototype has some other way to accomplish this sort of thing; I've not used it.

    Then if you want the DOM node you can always get it in the manner you mentioned; but like Dan said, I rarely find myself needing to do that, while I am constantly chaining methods.

  6. Josh Nathanson

    Crap, my html tags got eaten up in the above code example. I had put that "Hello" within a div tag as if to create a div on the fly.

  7. محمد زاهر غيبة » الأرشيف » أخبار متنوعة من الويب

    [...] .. * Ùˆ أخيراً Ùˆ ليس آخراً ØŒ مقال مقارنة جديد بين البطلين Prototype and jQuery … ملاحظة : منذ فترة تم انزال النسخة التجريبية [...]

  8. Kent Fredric

    For jQuery code blocks that are self-contained and collision friendly there is this handy notation

    jQuery(function($){

    $(".foo"); // Use like you would normally.

    });

    This does the following.

    1) Encapsulates the code cleanly so as not to leak into the dom.
    2) Waits for the DOM to be ready before executing
    3) Executes the function passing the jQuery object in as $

    This way $ doesn't exist outside this function, but does inside it, immeasurably helpful.