Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API design and jQuery [closed]

I have often heard that jQuery has made some poor API decisions. Although jQuery is not my favourite library it's the library I've used most often and I find it hard to point out specific mistakes in the API design or how it could have been improved.

What parts of jQuery's API could have been done better, how could it have been implemented different and why would that different implementation be better?

The question extends to both low level individual details of the API and high level details of the API. We are only talking about flaws in the API rather then flaws in the high level design / purpose of the library, jQuery is still a DOM manipulation library centred around a selector engine.

Because of the necessity of API freezing in popular libraries, jQuery is stuck in it's current state and the developers are doing a great job. As can be seen by the recent .attr vs .prop change the developers do not have the flexibility to change any of their design decisions (which is a shame!).

One specific example I can think of would be

$.each(function(key, val) { })

vs

$.grep(function(val, key) { })

which is confusing enough that I have to double check what the parameters are frequently.

Please do not compare the jQuery library to full fledged frameworks like dojo and YUI and complain about lack of features.

like image 285
Raynos Avatar asked May 19 '11 19:05

Raynos


1 Answers

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

like image 152
user113716 Avatar answered Oct 03 '22 16:10

user113716