API design and jQuery [closed] API design and jQuery [closed] jquery jquery

API design and jQuery [closed]


  • .load() is overloaded with entirely different behavior depending on the arguments passed

  • .toggle() is overloaded with entirely different behavior depending on the arguments passed

  • too much overloading of the jQuery() function perhaps.

  • the .attr() you mentioned. The distinction from properties should have been immediate IMO.

  • .map( key,val ) but $.map( val,key ), and the this values are different.

  • non-standard selectors ought to have been kept out of Sizzle IMO. Javascript based selector engines should become obsolete in a number of years, and people hooked on the proprietary selectors will have a more difficult transition

  • poor method naming of methods like .closest() or .live(). What exactly do they do?

  • I recently discovered that you can't set the standard width and height attributes via the props argument when creating a new element. jQuery runs its own width and height methods instead. IMO, the spec attributes should have been given priority, especially since width and height can be set via css.

$('<img/>', {     css:{width:100, height:100},    width:100, // <-- calls method, why?    height:100, // <-- calls method, why?});
  • $.get() and .get() are entirely different.

  • .get() and .toArray() are identical when passing no arguments

  • toArray() and $.makeArray() do effectively the same thing. Why didn't they give them the same name like .each() and $.each()?

  • two different event delegation methods. .delegate() the sensible one, and .live() the magical "wow, it just works!" one.

  • .index() is overloaded with 3 behaviors, but their differences can be confusing

 // v---get index   v---from collection (siblings is implied)$('selector').index(); // v---from collection   v---get index$('selector').index(element); // v---get index      v---from collection$('selector').index('selector');

The first one is understandable if you remember that it only operates on the first element

The second one makes the most sense since jQuery methods usually operate on an entire collection.

The third one is entirely confusing. The method gives no indication of which selector is the collection and which selector represents the element whose index you want from the collection.

Why not just eliminate the third one, and have people use the second one like this:

 // v---from collection      v---get index$('selector').index( $('selector') );

This way it fits more closely with the rest of jQuery where .index() operates on the entire collection.

Or at least reverse the meaning of the selectors to fit in better:

 // v---from collection   v---get index$('selector').index('selector');

Here's another to think about anyway.

I have some concerns with jQuery's event handling/data storage system. It is praised because it doesn't add functions to on[event] properties that can close around other elements, creating memory leaks in IE. Instead it places a lightweight expando property, which maps to an entry in jQuery.cache, which holds handlers and other data.

I believe it then attaches a handler with in turn invokes the handler that you assigned. Or something like that.

Whatever the system is doesn't really matter. The point is that the connection between the element(s) and the jQuery.cache is that expando.

Why is that a big deal? Well philosophically jQuery is not a framework; it is a library. It would seem that as a library you should be able to use or not use the jQuery functions without concern for negative effects. Yet if you go outside jQuery when removing elements from the DOM, you've orphaned any handlers and other data associated with those elements via the expando, creating a nice and fully cross-browser memory leak.

So for example, something as simple as el.innerHTML = '' could be very dangerous.

Couple this with the jQuery.noConflict() feature. This enables developers to use jQuery with other libraries that utilize the $ global namespace. Well what if one of those libraries deletes some elements? Same problem. I have a feeling that the developer that needs to use a library like Prototypejs along side jQuery probably doesn't know enough JavaScript to make good design decisions, and will be subject to such a problem as I've described.


In terms of improvements within the intended philosophy of the library, as far as I know, their philosophy is "Do more, write less" or something. I think they accomplish that very well. You can write some very concise yet expressive code that will do an enormous amount of work.

While this is very good, in a way I think of it as something of a negative. You can do so much, so easily, it is very easy for beginners to write some very bad code. It would be good I think if there was a "developer build" that logged warnings of misuse of the library.

A common example is running a selector in a loop. DOM selection is very easy to do, that it seems like you can just run a selector every time you need an element, even if you just ran that selector. An improvement I think would be for the jQuery() function to log repeated uses of a selector, and give a console note that a selector can be cached.

Because jQuery is so dominant, I think it would be good if they not only made it easy to be a JavaScript/DOM programmer, but also helped you be a better one.


The way jQuery handles collections vs single elements can be confusing.

Say if we were to update some css property on a collection of elements, we could write,

$('p').css('background-color', 'blue');

The setter will update the background color of all matching elements. The getter, however, assumes that you are only interested in retrieving the value of the first element.

$('p').css('background-color')

MooTools would return an array containing the background colors of each matching element, which seems more intuitive.

The naming conventions for jQuery promote conciseness instead of clarity. I like Apple's strategy in naming things:

It's better to be clear than brief.

And here's an example of a method name from a mutable array class (NSMutableArray) in Objective-C.

removeObjectAtIndex:(..)

It's not trying to be clever about what's getting removed or where it's getting removed from. All the information you need to know is contained in the name of the method. Contrast this with most of jQuery's methods like after and insertAfter.

If somebody can intuitively figure out what after or insertAfter does without reading the docs or the source code, then that person is a genius. Unfortunately, I'm not one - and to-date, I still have to go to the documentation to figure out what the hell gets placed where when using these two methods.


patrick dw hit most of the points in his (fantastic) answer. Just to add to his collection with a few other examples.

An API is supposed to be consistent; and jQuery succeeds in a lot of areas (being very consistent for returning a jQuery object/ get value, as expected in a lot of cases). In other situations however, it doesn't do so well.

Method NamesAs already pointed out by patrick; closest() is a crap method name. prev(), and next() appear to most as if they do the job prevAll() and nextAll() actually provide.

delay() confuses a lot of people: In the following example, which do you expect to happen? (what actually happens?)

$('#foo').hide().delay(2000).slideDown().text('Hello!').delay(2000).hide();

Method ArgumentsA lot of the tree traversal functions are inconsistent with what they accept; they all accept a mixture of selectors, jQuery objects and elements, but none are consistent; which is bad considering they all do similar jobs. Check out closest(), find(), siblings(), parents(), parent() and compare the differences!

Internally, the "core" of jQuery originally contained lots of intertwined methods, that the dev team have struggled to split up (and done really well to), over the past releases. Internal modules such as css, attributes, manipulation and traversing all used to be bundled in the same big package.