Skip to content

Instantly share code, notes, and snippets.

@Raynos
Created December 1, 2011 14:15
Show Gist options
  • Save Raynos/1417030 to your computer and use it in GitHub Desktop.
Save Raynos/1417030 to your computer and use it in GitHub Desktop.
jQuery library critique

jQuery

Related: Why you don't need jQuery as an abstraction

$ itself is a god object. Everything goes on it. The standard plugin / extension architecture that is recommended is to just bolt more methods on $ itself!

Surely this is bad. An example would be how we have both $.load which is overloaded to do completely different things. If they were on two separate sensibly named objects $Container.load and $EventTarget.load. Personally I would deprecate the latter in favour of .on('load'

The animation should be it's own little modular thing, not bolted onto $. Ajax should be it's own little modular thing, not bolted onto $

$

This is overloaded to three functions. It would be more sensible to have select, construct and domready as there seperate entities.

$('<elem>', props)

When creating elements using the jQuery API it calls jQuery.fn.attr.call( selector, context, true ); which basically means the props run through the minefield that is .attr. That's just great...

Also props like width and height don't set the width and height properties, they run the width and height methods.

$.get, $.getJSON, etc

We have some subset of $.ajax short cuts which are uneven. These should be removed.

$.attr

What does it even do? It doesn't just set / get attributes. It does a whole bunch of weird logic for backwards compat.

:text, :checked :button

Useless, slow utility selectors. Having these things promotes bad and slow code. You wouldn't want to use them for performance penalities. They also make the CSS selector a joke by throwing propitiatory selectors in the mix.

At least split the selector engine into two, one that adheres to (a subset of) standards and one which have their own extensions.

.css

css isn't bad as such. But it's overused, a lot. We do need a cross browser style manipulation utility but we don't need documentation recommending you use it everywhere.

The community seems to forget the massive penalty that is causing re flows. editing in-line css is slow and should be avoided

.toggle

Another overloaded method that shouldn't be overloaded, that's just plain confusing

.wrap, .live

These shouldn't exist.

.each, .map, etc

Doesn't match the .forEach, .map, etc signature. Massively confusing

.map

Hey, lets flatten the returned array! Surely that's an useful "feature"!

.domManip

domManip executes all scripts irregardless of their status. It does not bother to check whether they are inserted into a document nor does it bother to check whether their "already started" flag is set.

The first is a flag indicating whether or not the script block has been "already started". Initially, script elements must have this flag unset (script blocks, when created, are not "already started"). The cloning steps for script elements must set the "already started" flag on the copy if it is set on the element being cloned.

.bind

Function.prototype.bind exists. Pick a better name

Swallowing exceptions and silent errors

jQuery never gives any error messages and tries as hard as possibly not to fail or bubble up internal exceptions. It just likes to swallow all errors.

.data

It only reads from data- properties once on load and never reads/writes to them again. This is frustrating.

Either it shouldn't have anything to do with data- properties or it should be a cross browser .dataset emulation, not some kind of halfway in between thing.

This does not help debugging at all.

.extend

extend only deep copies "plain objects". Which is rather useless if you use prototypical OO because properties with enumerable non-own properties are not plain.

This basically means the deep extend is a joke and should be avoided. There is no warning about this "feature".

Modularity

jQuery has no modularity. Want just ajax? Load the entire library. Want just events? load the entire library. This is simply a side effect of bad design and god objects. jQuery assumes every method exists, and everything references everything else.

Plugin model

The plugin model is simply bolt stuff onto $.fn which is basically the jQuery "class". There is absolutely no attempt at promoting sub classing here. There is also no mechanism for conflict resolvement.

Basically if you want to extend jQuery your encouraged to just add layer on top of layer on the already huge god object.

.get

Another name that's overloaded for $.get and $.fn.get

.index

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

Memory leaks

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.

noConflict

Useless method. Why would multiple libraries use the same $, name a single library that also uses $ and should be loaded on the same page as jQuery. If a developer uses prototype and jQuery on the same page or god forbid multiple versions of jQuery on the same page then they are doing it wrong. jQuery should not give them a tool to allow them to make that mistake.

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.

.append

Will not work with an array argument when it's clearly obvouis what it should do.

$.fn.extend

Will not extend the current jQuery object. It will only extend jQuery itself.

@NARKOZ
Copy link

NARKOZ commented Dec 2, 2011

what are your suggestions? prototype?

@Raynos
Copy link
Author

Raynos commented Dec 2, 2011

My suggestion is, if you want a production ready cross browser library use jQuery. It's the lesser of evils.

This is merely a summary to fight people who say "jQuery is the best library ever!"

Of course, personally I'm working on the DOM-shim once / if that ever becomes production ready I would recommend that instead.

@andyrwebman
Copy link

From what I can see of the DOM-shim, this is WAY more like what we need.

I have despised the jQuery syntax and impossibility to debug ever since I saw it - it's as if someone decided that modern coding syntax was too easy to understand and needed to be made more geeky.

It reminds me of code where people try to do a really complex series of functions or calculations in a single line, when it needs to be broken up into small, logical steps, allowing you to breakpoint each and see where it went wrong. For example, if I wanted to make all DIV elements run a piece of code upion mouse over, I would like soemthing like this below:

var mySelector = new ElementMapper(); //this would be an object with the power to do stuff like jQuery
mySelector.pattern="whatver set of patterns"
mySelector.events=new Array("onMouseOver","onClick") //list of events you want doing
mySelector.function="doMouseOver(this)";
mySelector.setEvents(); //this would set all matching the pattern

function doMouseOver(SourceObject)
{
//run the actual code here
}

I loathe inline declarations for functions like you see in JQuery, especially when you see them nested, it's so messy, and again difficult to debug. It teaches you appallingly bad programming habits.

I really can't see why people aren't demanding this, or why people are including jQuery as a standard tool in proper OO frameworks . It's like a filing cabinet where everything is filed under "P" for "People".

If the DOM-shim can expose the DOMs of all browsers in a consistent manner, this might just be what we need to sound the death knell of jQuery, by beating it hands down for versatility and stealing its "cross browser" thunder.

If it can also come with a library of objects for all the handy functions - like the example shown - it will be great.

Good luck dudes.

@Raynos
Copy link
Author

Raynos commented Feb 3, 2012

No offence but your examples are horrid. however ill write abstractions as and when needed like i did with nodecomposite.

@andyrwebman
Copy link

Raynos,
It's hardly a masterpiece of coding so I won't take offense, although I would like to know how you'd write something you don't consider as "horrid". I'm used to the vb.net world of classes so this isn't how I'd normally write code, it was just to show an example of something working like jQuery but broken up into small steps, with the function defined separately from the code that sets the event handler.

I'll be interested to see what you consider nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment