Like most programmers who’ve done Rails development, I’ve become very familiar with the Prototype library for JavaScript. Even apart from being built into Rails, Prototype was a natural choice for me. I knew JavaScript pretty well before I started working with Prototype, and was very pleased by how the library filled in some of the weak spots in the language. Additionally, having already been a Ruby programmer for a few years, Prototype’s philosophy seemed very natural; it clearly draws inspiration from Ruby.
Along the way, though, I’ve been hearing an increasingly strong chorus in favor of jQuery. I had taken a cursory look at jQuery and was impressed, but didn’t see anything compelling enough to make me switch. But increasingly the voices favoring jQuery have included people I really respect, including (over the past few months) several of my colleagues here at Relevance.
I’ve now spent serious time working on two different projects with jQuery. I’ve worked alongside some experienced jQuery users, and really increased my knowledge and level of comfort with jQuery. The work has included a reasonable variety of JavaScript tasks, from simple to complex, so I’ve had a chance to enjoy jQuery’s sweet spot and also to see how it stretches.
And here’s the capsule summary: jQuery is a very nice piece of work, and makes some common tasks easier than their Prototype equivalents. Where it’s good, it’s very good indeed. But its design is uneven, and its scope is limited. For me, at least, Prototype is still the tool of choice. I think it’s a richer, more thorough, and overall better designed library.
I don’t intend this to be an anti-jQuery screed (although I will rant a little about a couple of things that seem particularly poorly designed). Neither is it an exhaustive comparison of Prototype and jQuery. Simply put: praise has been lopsided in favor of jQuery of late, and I feel like singing the praises of my personal favorite.
Note: in this post I’ll be showing code examples using both Prototype and jQuery. To keep things straight, I’ll color-code the listings. Prototype samples will have a green background:
// This is Prototype!
$('form').hide();
Samples using jQuery will have a yellow background:
// This is jQuery!
$('#form').hide();
The occasional sample that shows the “Plain ol’ JavaScript” way to do things will have a grey background:
// This is ordinary JavaScript!
document.getElementById('form').style.display = 'none';
Where jQuery Comes Out on Top
jQuery clearly has a core focus and philosophy that unifies its design. The idea seems to be that, since most of what you want to do with JavaScript is to find HTML elements and manipulate them, the design should be optimized in favor of that common use case. And jQuery certainly excels in that case. The jQuery documentation emphasizes the ability of many jQuery methods to be “chained” (because they return the jQuery object). I’m personally more impressed with the implicit iteration: when jQuery is used to find a set of elements, modifications are automatically made to all of those elements.
I would describe the “three pillars” of jQuery this way:
- searching for elements using CSS selectors
- operations implicitly applied to all found elements
- ability to chain operations
Each of those are powerful features, but more importantly, they work beautifully together. They allow jQuery programmers to express complex manipulations of the DOM in very concise ways, without losing clarity.
This section isn’t very long, so someone skimming this post might get the idea that I don’t think jQuery has a lot going for it. But I really admire this aspect of jQuery. The coding style that arises from these features shapes the way you do everything in jQuery. Furthermore, the fact that three such simple ideas can have such enormous positive effects on code written using the library speaks volumes for the power of good design.
It’s just a shame that the rest of jQuery is not as well designed.
In some ways, it’s harder to make the case for Prototype, because that case depends on numerous small details, some of which are strengths of Prototype, and some of which are weaknesses of jQuery.
However, I have to say that, while jQuery wins in this area, it doesn’t win by as much as some would have you believe. Most of the comparisons I’ve found on the web are rather ridiculous, because they compare jQuery against very poor examples of Prototype usage. Take this example:
// Good jQuery
$('blah blah').addClass('foo');
compared with
// Prototype (explicit iteration)
$$('blah blah').each(function(element) {
element.addClassName('foo');
});
There’s a much better way to do that in Prototype:
// Prototype (implicit iteration)
$$('blah blah').invoke('addClassName', 'foo');
The invoke method in Prototype will apply a named method to each element of a collection.
Prototype’s DOM methods are also chainable, even when using invoke.
Where It’s a Wash
Critics of Prototype have tended to focus on three issues: code size, performance, and namespace pollution.
These days, Prototype and jQuery have about the same code size. Prototype is a little larger, especially since it doesn’t ship with a minimized version. But if you care about code size, that’s easily remedied. It’s not hard to run a JS minimizer. It’s also worth pointing out that the very small code size gap is not gratuitous; Prototype has more functionality. (In looking at this issue, I’ve compared core Prototype against core jQuery, and also Prototype+Scriptaculous against jQuery+jQuery.ui.)
Although Prototype’s performance has not always been good, it has improved a great deal, in many cases by learning lessons from how jQuery has done things (and in some cases, the patches were even submitted by the jQuery developers). Today, Prototype’s performance is close to that of jQuery, and the very poor performance Prototype used to have for some situations (and in some browsers) has been eliminated.
The other issue is namespace pollution. Prototype adds several top-level names to the JavaScript global namespace, and adds numerous new methods to built-in JavaScript classes. There is a potential for namespace collision, either with other JavaScript libraries or with new JavaScript features. (And it’s more than just potential; real collisions of both kinds have occurred.) jQuery, on the other hand, takes care to limit its use of existing JavaScript namespaces, and can be configured to use only one global name (jQuery).
I fully understand the dangers of Prototype’s approach, but after living with both it and jQuery for some time, I’ve come to appreciate that it also has important benefits. JavaScript is a language that is extremely dynamic and open, and also deeply flawed. Prototype’s developers have chosen to take advantage of that openness to try to fix (or at least smooth over) many of JavaScript’s biggest weaknesses. The fact that Prototype’s facilities feel well integrated into the language is a huge win for me, and it seems to be worth the cost. I don’t expect this argument to convince anyone; this is the kind of thing that boils down to taste and priorities. But for me, Prototype’s and jQuery’s approaches to namespace management have complementary costs and benefits, and I don’t think this is a good reason to choose one library over the other.
Where Prototype Wins
Now I’ll describe where I think Prototype has the advantage, touching on three different areas: a more polished API, some issues with the way jQuery uses this, and a broader, more versatile array of programming facilities.
API Polish
I’ve already mentioned how beautifully designed jQuery’s core is. The problem is that the parts of jQuery outside that core are often poorly designed, in ways that really frustrate me. I’ll describe four.
When using the each method for iteration, the arguments to the iteration function are in the wrong order. (I know, I know … if you program the “jQuery way” you won’t actually use those arguments. I’ll address that later.) Here’s an example:
// jQuery (non-idiomatic)
$.each(collection, function(index, item) {
item.whatever();
});
When iterating over a collection, you nearly always want to work with the element of the collection, and you rarely need to actually refer to the index. The arguments should be the other way around, so that you could omit the index argument in the vast majority of cases where you don’t need it. Here’s the equivalent in Prototype:
// Prototype
collection.each(function(item) {
item.whatever();
});
Prototype’s each does pass an index argument to the iteration function, but it’s the second argument, so it can be omitted if not used—which is nearly always.
But jQuery can’t even be consistent about this. Here’s how jQuery’s map works:
// jQuery
var result = $.map(collection, function(item) {
item.whatever();
});
The argument order for map is item, index—just what you want, but it’s sad that it’s inconsistent with each.
And jQuery’s map is broken in other ways as well … the traditional definition is that the result array has the same number of elements as the original, but with jQuery’s version that’s not true. (What I refer to as “the traditional definition” of map is the one used by Common Lisp, Scheme, Haskell, OCaml, Erlang, Ruby, Python, Perl, Scala, and more.) I won’t dwell on the details of how jQuery’s map is broken, but one consequence is that it’s impossible to use it to produce an array of arrays, because any arrays returned from the mapping function will be flattened into the result array.
jQuery has a unique method. It returns all the unique elements from an array; that is, it eliminates the duplicates. Very handy. But for some reason, it only works on arrays of DOM elements. It silently fails (by returning a copy of the original array) if you pass it an array of anything else. This is a known problem, but the bug was “fixed” by just updating the documentation to make the behavior clearer. How difficult would it have been to make it work correctly? (Answer: not very, because the bug report came with a patch and tests.) Prototype’s uniq method works in both cases.
Finally: jQuery also has an inArray method. You can call it like this:
// jQuery
$.inArray(value, array)
But what does it return? Well, “in array” is a question that has a yes or no answer, so I’m guessing a boolean. Let’s see what the docs say:
Determine the index of the first parameter in the Array …
Ah, it returns the index. But that’s OK … JavaScript supports the notion of “truthiness”, meaning that objects other than true and false can be used where a boolean is expected. Truthiness is useful, because it means boolean results can actually be useful outside of strictly boolean contexts, and returning the actual index in this case is a great example of that. So as long as inArray returns false, null, or undefined if the value is not in the array, we’re in good shape. But I left out part of that documentation above. The rest of it is:
… (-1 if not found).
Gack! How useless is that? The name of the method implies that it’s a boolean query, but the result value is not useful in a boolean context. And if you just try using it that way, making an assumption based on the name, you’ll have fun debugging it, because there won’t be an error; it’ll just always be true.
For fifty years, programming languages have been using two common names for the job that inArray does: index and position. Having a method called inArray that works like this is just sloppy library design.
Leave this Alone!
When complaining about iterator arguments to jQuery’s each, above, I mentioned that the “jQuery way” is not to use the arguments to the iterator function at all. That’s because when jQuery’s each calls your iterator function, it does so in such a way that the variable this is bound to the current item. So the idiomatic way of using each in jQuery is:
// jQuery
$.each(collection, function() {
this.whatever();
});
That’s the kind of decision that makes really simple cases very easy, but only at the expense of a lot of confusion when things are a bit more complicated. That’s because this is already an important variable in JavaScript, and the callback often needs to refer to the value of this from the scope in which it was defined. Functions in JavaScript are closures, and programmers often need to exploit the ability to refer to variables in the surrounding scope.
Here’s an example. I have an object (called chart), and in a method on that object I need to iterate over an array (stored in the property columns), generating a header for each item using buildHeader, which is another method on chart. Within methods of chart, of course, chart is referred to as this. The basic JavaScript way of doing that is:
// Ordinary JavaScript, in a method body.
for (var i=0; i<this.columns.length; i++) {
this.buildHeader(this.columns[i]);
}
But that manual iteration sure feels clumsy; it would be nice to be able to do that with each. Let’s do that with jQuery:
// jQuery (incorrect example)
$.each(this.columns, function(i, item) {
this.buildHeader(item);
});
But that doesn’t work; this within the iterator function has been rebound to the current item. The this variable from the surrounding scope has been shadowed by a different this that refers to the current iteration item. But unlike i and item, this has been shadowed implicitly, by jQuery’s implementation of each.
The preferred jQuery way to write the example is to provide an alias for this that doesn’t get shadowed by each:
// jQuery (correct example)
var me = this; // provide alias for this
$.each(this.columns, function() {
me.buildHeader(this);
});
But notice that this in the iteration function is a different this than in the immediately preceding line, even though conventional JavaScript closure semantics would lead you to believe they were the same. When building a complicated class, jQuery’s (ab)use of this can make things very confusing.
Here’s how to do the same thing in Prototype:
// Prototype
$A(this.columns).each(function(item) {
this.buildHeader(item);
}, this);
Messing with this implicitly is a terrible design decision. It breaks the conventional semantics of JavaScript, rendering the resulting code unclear, and presenting barriers when you need to exploit the usual semantics. I understand the desire to have an implicit iteration variable; good names might be it or item. Unfortunately, JavaScript doesn’t provide a mechanism for jQuery to set those variables from outside the function; it can only manipulate this. But that’s not enough justification for the design choice jQuery makes.
If jQuery’s each were properly designed, one could write the basic iteration idiom this way:
// jQuery (with hypothetical fixed 'each' method)
$.each(collection, function(it) {
it.whatever();
});
Would that be so bad? No; in fact, it would be a huge improvement. This style is just as easy in the simple case, and far less troublesome in more complex cases.
Broader Scope
I mentioned earlier that jQuery has a core of functionality built around querying and manipulating DOM elements. It also has mature support for Ajax operations. Beyond that, though, jQuery doesn’t aim for very extensive facilities. (Of course there are numerous plugins and add-ons that do all kinds of things, as there are for Prototype.)
Prototype, even in the core library, has broader goals. It also has good facilities for DOM searching and manipulation, and for Ajax operations. To a greater degree than jQuery, though, Prototype attempts to raise the level of JavaScript programming across the board. To me, the result is a big win for Prototype.
For example: Prototype includes a nice, simple class-based inheritance facility for JavaScript. That might seem a bit heretical for a prototype-oriented language like JavaScript (and especially for a library called Prototype). But the strength of the prototype-oriented style of OO is that it gives you freedom to move beyond the class-based mechanisms. That doesn’t mean that classes are useless; actually, they’re the most appropriate way of organizing your code a lot of the time.
Prototype also adds useful new basic types (such as ObjectRange, Template, and a true Hash) and adds a wealth of supplementary methods to most of the built-in JavaScript types, greatly increasing the ease of basic programming in the language. For advanced JavaScript programming, Prototype’s new Function methods are worth the price of admission all by themselves. jQuery makes working with the DOM very easy, but is sparing in its assistance related to other JavaScript objects. Prototype, on the other hand, helps across the board.
So while jQuery might be easier to get started with, Prototype grows with you better. Most web developers get started with JavaScript by doing relatively simple DOM manipulation, and jQuery really excels there. But as you get more comfortable and begin trying to do more, you may find that jQuery doesn’t help you as much. Prototype makes JavaScript programming lots of fun even in circumstances where jQuery feels constraining.
Conclusion
I don’t think this makes a slam-dunk case for Prototype over jQuery. And certainly jQuery could improve; its design is not fundamentally limited. (For that matter, many of what I consider the missing pieces in jQuery are available as plugins.) It’s unfortunate that some of jQuery’s API flaws can’t be fixed without breaking compatibility, but in a future version even that may be an option.
At a minimum, though, Prototype can hold its own. For me and many others, it’s still the JavaScript library of choice.
(Thanks to Stuart Halloway, Chad Humphries, Larry Karnowski, Adam Keys, and Jason Rudolph for their comments—in some cases pro, in others con—on a draft of this article.)
Comments
Although I haven’t looked into jQuery much, it looks to me too much like PHP. Functions everywhere, instead of the nice OOP approach as for instance Ruby does.
Thanks for this post, as I am now a bit more confident, not switching to jQuery yet (it was very low on my todo-list)
Nice points, messing around with “this” is a serious deal-breaker as far as I’m concerned, especially when writing considerable amounts of sophisticated OO-style JS.
Seriously, if you’re looking for the best of both worlds, you should investigate MooTools. It basically combines all of your Prototype WINS with the jQuery WINS. It also cleanly allows for multiple inheritance.
We’re using it in our opensource metaweb project ShiftSpace (http://www.shiftspace.org). Without it I’m not sure we could have sanely written the 20k or so lines of JavaScript that makes it all work.
For example:
var parts = selectors.split(','); var target = event.target; var hits = parts.map(function(selector) { return this.hitTest(target, selector); }.bind(this)).flatten().clean();The above code maps to an array of arrays, flattens it into a single array, and removes all nulls.
if you haven’t, you should really give MooTools a try as well. http://mootools.net/
I’m pretty sure your `each` example won’t work because you’re not binding `this` to the anonymous function. `this` is the window object in your example.
I still like Prototype too, but I’ve used jQuery for some website badges/JSONP stuff and it shines there. With that said though, I’ve been using MooTools more. It’s very similar to Prototype but has support for event simulation (good for testing), cross-domain JSON, and custom events (prototype’s custom events are tied to DOM objects or document/window. FWIW, there is peices of code here that solve most of my issues – http://github.com/kangax/protolicious/tree/master.
I absolutely agree with you, but I’ve found the Prototype often feels a bit messy in areas as well. I’ve recently grown attached to mootools (http://mootools.net/), which has a lot of similarities with prototype but feels a bit cleaner to me.
Justin (Palmer), for brevity I left the surrounding code out of the example you’re referring to, but I did mention that the entire example was part of a method body, so ‘this’ is actually the object on which the method was called.
And to the MooTools crowd: OK, I get the message! I’ll take a serious look. :-)
Hi Glenn,
Justin Palmer is correct, the “this” inside the function passed to each refers to the global “window” object, not the one in which each was called.
I’m not sure how this will come out in the comments, but try running the following code to see which buildHeader is called:
function buildHeader() { alert("this == window"); } var grid = { columns: ["a", "b", "c"], headers: [], build: function() { this.columns.each(function(item) { this.buildHeader(item); }); }, buildThis: function() { this.columns.each(function(item) { this.buildHeader(item); }, this); }, buildHeader: function(column) { this.headers.push("<" + column + ">"); } }; grid.build(); grid.buildThis(); alert(grid.headers.join(" "));Excellent post. I wrote a similar post comparing MooTools’ design philosophy to jQuery that you might find interesting. I think that you should spend some time with MooTools. It’s both the formal upgrade to the JavaScript language that you like about Prototype and the DOM/Chaining/Ajax/Effects functionality that everyone loves about jQuery.
Egads. When I started my previous comment there was only 1 comment visible, when I submitted it, there were half a dozen. My bad. Didn’t mean to join the mob.
Thanks for the post. I am a long time prototype user and really like it (especially since they fixed the egregious global collision issues a while back). It seems that there is this huge ‘jQuery rocks, prototype sucks’ momentum around today, and I never understood why. I looked a jQuery a few times and essentially thought “not different enough/nicer than prototype to warrant switching”. Glad to see someone who’s looked harder than me that agrees.
Douglas, thanks … Justin Palmer was correct. (Adam Keys actually caught that gaffe when he reviewed my post, and I forgot to get the update in, which is why I jumped to the conclusion that Justin was mistaken.) I’ve updated the example.
Cheers Glenn. I think my favourite Prototype method, which I include even when working with jQuery, is Function.bind. This lets you write the example above like this:
Assuming a buildHeader which returns headers rather than pushing them into storage.
Basically what you’re looking for is MooTools, as other have pointed out. It’s API makes sense from start to finish, and I doubt you can come up with cleaner, more reusable code with any other library out there.
I consider myself proficient in both jQuery and Prototype, and must say I prefer jQuery. I can also see why people would prefer Prototype. They are both excellent libraries. One place Prototype needs to catch up, however, is events. Not having a way to programmatically execute a built-in event hurts. Especially for creating unit testing on the page, it’s nice to grab the DOM element and just .click() it. With Prototype, the .fire only works for custom events.
As an interesting side note, if you are using Prototype and jQuery together, then
jQuery.each(function() {
}.bind(this));
works the Prototype way and ‘this’ inside of the jQuery array gets overwritten with whatever the context of this is outside of the loop. Fun, huh!
Hi Glen, not to nag, but your update is still wrong. :-) It should be:
Glenn,
I’m a Rubyist by trade so Prototype seemed to fit what I wanted to do (think like I would in Ruby and apply the same coding type to my JS), but after really sitting down and realizing what Javascript is capable of (without a framework) and understanding jQuery’s goals, I’ve really found that I prefer jQuery. I understand that people will throw out contrived examples about either framework, and I am also fully aware of the problems present in both.
I most definitely think my affinity towards jQuery stems from a very good understanding of Javascript, prototype-based inheritance, closures, etc. Javascript is not a class-based inheritance structure and it feels like the Prototype library is trying to squeeze JS into a nice little Ruby box. At least it’s not to the extent of http://jsclass.jcoglan.com/... Each is its own language and should be used as it was meant to be.
Developers (myself included), when learning a new language, will often apply a programming style they used from a previous language to the language they’re learning. When learning Ruby especially in the beginning, I had a very hard time wrapping myself around the simplicity of the language (I was doing C# development at that time). Now, almost three years later, I write Ruby, applying idioms and standard practices in all my code. I don’t try and write Ruby as I would’ve C#, and I think that many Ruby devs are selling themselves short by really sitting down and learning Javascript.
Anyways, I don’t mean to start a framework war, and I’m still not 100% sold on jQuery. It’s my preferred JS framework currently for the sole reason that it’s geared primarily on the DOM and its manipulation, which I feel is the main purpose of JS.
If you’re interested in some good Javascript reading, I suggest Javascript: The Good Parts (http://oreilly.com/catalog/9780596517748/). It really opened my eyes to what Javascript is both capable of and geared towards.
Best of luck, keep your ears open, and let the discussions continue!
Hi Glenn, I am a pretty ardent jQuery guy, but I’m also an ardent critic for the areas I feel it does poorly. I have to say I think your post was really even handed and quite refreshing.
I do have to disagree on a couple of points. I would definitely say that neither jQuery nor MooTools nor Prototype are really representative of Javascript as a language. Prototype is definitely meant to make Javascript friendly for Ruby developers, jQuery is designed for front end designers and developers, and MooTools is kind of a quasi-mix. I would say YUI is probably the closest you’ll get on that level, but Dead Edward’s base is probably the purest.
That is neither a criticism or a praise, but more or less just an observation.
I have to agree on the parameter order between methods being a pain. It was brought up on the dev list before, and basically, the feeling was to keep backwards compatibility, since it’s “easy” enough to remap it with a plugin. I still think it should be consistent and have a backwards compatibility plugin, but it is what it is.
The remapping of this isn’t that big a deal to me, but I think the issue that bothers me right now is the lack of scoping that Prototype, MooTools, YUI, dojo, and practically every framework allows. I know it’s been addressed, but imo, it needs to be done sooner than later.
Lastly, I think some of it comes down to preference. For me the namespace pollution is far too high a cost for me with Prototype, and I think jQuery’s ajax handling is quite exceptional.
I also have to say that while the plugins environment leads to quite a lot of shoddy code that is hard to maintain, it also provides a really large ecosystem that encourages a lot of innovation.
Either way, thanks for the great article and the fairminded approach, and well thought out criticisms.
Good writeup. I may take even longer to pick up jQuery. The “this” issue seems like a big one to me – it would drive me nuts. I didn’t realize that Prototype DOM methods were chainable, so that was good to see. Thanks!
Gee, just take a look at MooTools, you won’t be disappointed! Very concise code but a little bit of a learning curve.
Cheers! Daniel
Hi Josh,
unitest.js includes a method for simulating native events (keyboard and mouse). It only works on Firefox, though.
I think the community assumes this is something to improve, though.
I could be wrong about this, but there seems to be something wrong with your examples of problems with the ‘this’ keyword.
$.each(collection, function() { this.whatever(); });The reason jQuery works this way is to maintain symmetry with event handlers. Replace ’$.each(collection,’ with ’$(collection).click(’ and you’ll hopefully see what I mean.
In fact, there’s nothing stopping you from implementing Prototype’s bind() method in your jQuery apps, and then binding the functions to whatever context you want in exactly the same way that you would do in Prototype.
I think that there’s a more fundamental point here though. I don’t think that closures should generally assume that they know what the ‘this’ keyword is going to evaluate to. When you set a closure as an event handler, when it gets called ‘this’ will point to the DOM element on which the event is fired, not the context of the outer function in which the closure was defined. Far from doing things the wrong way, jQuery emulates a pattern very familiar to most JavaScript developers. In fact, the discipline of not relying on knowing what the ‘this’ keyword will evaluate to is something that I think JS devs should regard as important and not something to be ignored. Importantly, it’s also worth pointing out that Prototype messes with ‘this’ just as much as jQuery does, it just uses a different method of doing so.
Thanks for the comparison. I have been looking to switching from prototype to jquery only because jquery seemed to have a much larger user base. I, however, am very happy with prototype.
This writeup made me realize that just because everyone else is doing it doesn’t make it right. I’m going to stick with prototype.
Cheers.
At least in Perl and I guess also in other languages, the map operator/function is allowed to return more elements than were passed in, so in that respect, jQuery behaves like the others.
IMHO they both suck in one way or another. To me MooTools is the best of both worlds.
So you decided to do the same but reverse the tendency, good Prototype poor jQuery ?
FYI jQuery’s each was properly designed:
I don’t think one framework is “better” than the other, it’s only a matter of taste. The most important thing is to work with a framework that feels intuitive to you and with which you are comfortable working with.
@Justin – You can send the context as the second param of “each” http://www.prototypejs.org/api/enumerable/each (It’s missing from the Array#each docs but the same applies.)
@Glenn – Because this.columns is an array there is no need to use the $A method.
[code] this.columns.each(this.buildHeader, this); [/code]
MOOOO!
Having spent a good deal of time learning my way around Prototype, I prefer it for many of the same reasons you mention.
While there are some neat plugins for Prototype out there that add in some cool things, there are definitely things that Prototype is severely lacking that need to be added to the core: Namespacing/Packing (and dependency resolution) and also a first-class unit testing construct… perhaps a thin facade over something like http://ejohn.org/blog/fireunit/
@jake – I stand corrected sir. Was that a recent addition or have I just overlooked it all this time?
About code size: I’ve always thought of jQuery to be roughly equivalent to Prototype + Scriptaculous. There are a few extra components in Scriptaculous that are not in the jQuery core, but a whole swathe of advanced UI controls in jQueryUI that don’t appear in Scriptaculous.
Aside from that, I find jQuery’s ajax handlers much simpler to use, but that might just be me.
I have always treated Prototype as JavaScript as it should be. The language extensions make my code really readable. I am really comfortable with Prototype. On the other side when working with jQuery is odd for me. Watching many newbies, they understand and work better than jQuery, because for them prototype is too magical. Great post :)
@justin: that was the change I made after Douglas set me straight.
@hamish: obviously the code size comparisons aren’t exact because of different feature sets. And Prototype is slightly larger—but the point is that there’s not enough difference in code size to make much difference.
@h3: yours is my favorite comment yet. If you think of jQuery’s each as iterating over Objects (of which Arrays are just particular examples) then having the parameters ordered as (k,v) makes sense (and it’s ‘map’ that’s broken). But that (in my experience) is a very unusual usage, and in the more common usage the parameter ordering is inconvenient and unintuitive (to me).
As for your last paragraph: I hope that’s exactly the message that came through in my post; it’s certainly the message I wanted to convey. The choice is largely a matter of taste, and both frameworks have a lot to recommend them.
(Oh, and one last thing: I tried very hard not to include poor examples of jQuery usage, or to label them clearly if I did. If I slipped up, please show me how! Although I prefer Prototype, I know I’ll be using both in the future, and I want to improve my understanding of jQuery as well.)
The Moo zealots seem especially irritating today. Mad cow disease?
Why I still prefer jQuery to Prototype, or jQuery to Mootools Just whith this first exemple http://mootools.net/slickspeed/
The fastest in speed and validity test selectors for frameworks, is jQuery. Mootols is the second and prototype is the third.
and the other reason is the large community of jQuery and the large number of plugins.
A french man ( sorry for my english ;-) )
At first, I really enjoyed reading your article, it’s good to see an objective comparison between frameworks from your own user experience. Myself, i’m a MooTools user, but some collegeaus of mine are jQuery fanatics. I don’t hate or misprise other frameworks, like i think it’s a matter of taste (and javascript experience) to make a proper choice between frameworks. I really like the extending of Native’s within prototype and mootools, which makes it very flexible and rock solid.
@thomtom … why bother of those speeds, 20ms diff between mootools and jquery with same results returned, i don’t base my judgement on that, cleaner coding style and extensibility is much more preferred than those tests.
Hi Glenn One will have to agree that many of the jquery flaws pointed out by you are correct, and make sense. However, in my opinion Jquery has a smaller learning curve than Prototype—and that itself might be the reason for the growing support for the former. What are your thoughts on this?
And, jQuery 1.3 has just been released. Check out the Delegation timings in particuar
http://docs.jquery.com/Release:jQuery_1.3
That’s a big reason to use jQuery instead of Prototype in a large event heavy application.
Sizzle looks cool – would be great to have a common selector interface between the frameworks.
I have been a hardcore devotee of jQuery since shortly after its debut 3 years ago. Your article is one of the most intelligent and factually accurate criticisms of jQuery I’ve read in all that time. Thanks so much for taking the time to explain your point of view.
For my part, I think it’s far too easy to claim that “JavaScript is broken” before applying patches to the language. I am personally not comfortable with the notion of altering a language to mesh with a subjective viewpoint, even if it is a widely shared viewpoint.
jQuery is a library that encourages certain quirky programming idioms. But Prototype is a dialect of JavaScript that alters the language significantly even before it is used by client code.
A programming language is a standard, just like the other standards that are so fundamental to web development today. I think that “fixing” JavaScript is comparable to adding a proprietary extensions to HTML or CSS to one browser.
@Glenn, the only favourable argument here in favour of Prototype is jQuery’s bad judgement on ‘this’ within .each(). Me thinks, that barely qualifies as a reason to not adopt it and as you and others claim, the remaining comparisons favour jQuery or split hairs… Parameter ordering? Come on! Have you seen the PHP String library?.
I recently switched to jQuery after spending more than a year with Prototype and built some very rich applications relying entirely on the framework. A week ago, I adopted jQuery after just spending 3 hours with it. The decision was just that easy but I pragmatic and stand strongly behind DRY and user-centric design—things Prototype drastically lags behind when compared to jQuery.
You can read my comparison of jQuery and Prototype, maybe it will help you see things from a practical, day-to-day type of thing.
I’ll second Mootools as others have suggested though I personally prefer to stick to a framework that I think will be around for a long time and has a lot more developers, industry adoption, bigger community and hence better user testing, richer ecosystem with things like plugins, a better KB, more responsive forums and so on. But most of all, it gets things done. Fast and easy. Wasn’t that what put PHP on the map? and then Ruby?
People advising jQuery or Mootools over Prototype are most likely lazy fanboys, designers that don’t need to be coders or bad coders.
Prototype simply has the most elegant syntax out there, even John Resig agrees on this. Reading a bit of Prototype makes sense, whereas when reading and writing jQuery you need the documentation closeby to make sense of it all.
That’s why every jQuery release comes with a new experiment on how do proper documentation, they just never get it right with failed naming conventions. These frameworks need to get serious about their API instead of coming up with ambiguous names to just be different from Prototype.
Elegance makes the learning curve on Prototype much smaller then jQuery. When you look at the core it turns out Prototype packs a lot more stable goodness to work with, saves you the time of having to plug in a ton of badly coded extensions.
The failed Prototype port called Mootools just tries to be different but never realy got it right as well. Mootools core should have contributed back to Prototype instead of going for a bit of fame trying to fix something that didn’t need a fix.
Ah boy. I was writing a nice comment when I accidentally hit ‘Enter.’ All I was saying was that I know people already suggested MooTools, but I must do the same.
I used Prototype for about 1.5 years and loved it. I was hesitant to try MooTools but was hired somewhere that uses it. Now I see why it is better in a lot of ways. But, I do say, Prototype has a lot of nice methods that MooTools lacks.