> Second: Stop using DOM libraries out of habit! If your target browser is IE8 or above, jQuery hardly provides any features that aren’t shipped on the host object anyway.
Nope, sorry, 9 times out of 10 the provision is theoretical and the interface is garbage. querySelector is pretty much the only one which does not suck — hence it being used as an example every single time.
* Querying or altering elements? Verbose shit.
* Binding events? Verbose shit.
* Delegating events? You've got 2 different specs, the most recent one is unimplemented and the older one is prefix-implemented everywhere (and useless as far as I know).
* Inserting elements in a DOM tree? Oh boy you're going to have a fun time manually traversing crap until you can reliably use insertBefore.
* Creating a node with text in it? You're in for 3 different statements, and that's if you're not trying to add attributes as well
* Manipulating classes? Hello broken regex search&replace. Oh you're targeting IE9 anyway? Well fuck you still, because Element#classList is IE10+.
* Playing with data-* elements? I hope you like getAttribute, because Element#dataset is MIA in MSIE.
* And bulk operations? What, you think querySelectorAll or getElementsByClass is going to return an array? Dream on, you may get something array-like in DOM4 if you're lucky. That means IE15, maybe.
Every single time I tried to get by with raw DOM, I fell back on zepto or jquery, life's too short for shit APIs and the DOM is exactly that. I don't code in raw DOM for the same reason I've stopped coding in assembly: I value my life more.
Now there are issues with jQuery, but these issues are generally that jQuery makes it easy to do the wrong thing (it's important to note that it also makes it easy to do the right thing, and improves that all the time, the "ease of doing the wrong thing" is just a side-effect of making things easier in general, the library does not specifically drive the user to the wrong thing) (except for animation maybe) e.g. keep doing noop work on empty selections, repeatedly select the same elements over and over again instead of caching the selection or not realizing you're doing a batch operation of adding a class or event on hundreds of DOM nodes in a single line.
The DOM itself does not fix this, it just makes these things so incredibly and obviously painful you look for other ways to do it to try and slightly alleviate the pain.
You get the same result out of thinking, and not blindly using jQuery.each and the like.
Maybe I'm neurotic but if I know I can speed up my application 100x by typing .addEventListener('click', fn) instead of .click(fn) I'm going to do that every time and not lose any sleep over it.
In case anyone reading doesn't realise* - that's not the kind of thing you'd be doing to get a speed up. I can't think of how addEventListener could lead to a 1.001x speedup of an app, let alone a 100x. You don't ever need to create listeners in loops, so a single operation like that just isn't a optimisation target. If you need to listen for an event that could come from lots of nodes, listen for the event bubbling up to the parent of those nodes.
* I'm sure Matthew realises but just gave the first example that came to him.
I didn't mean event listeners specifically, I meant trading all of the normal DOM APIs for less verbose and more consistent jQuery alternatives is a trade of performance. On a fast desktop computer that tradeoff is an easy one to make, but in mobile it still arguably isn't.
> Maybe I'm neurotic but if I know I can speed up my application 100x by typing .addEventListener('click', fn) instead of .click(fn)
You can't though, not even close. You can speed up your application significantly by using event delegation on a parent instead of binding an event to each element, but the raw DOM makes this a giant pain in the ass in the general case.
No way - even if it was the sole performance bottleneck in your application (which as I've commented above is absurd, and a sign you're doing it so very, very wrong). Even if your application was:
var i = 100;
while(i--) els[i].addEventListener("click",fn);
it'd be untrue jQuery is nowhere _near_ 100x slower. Profiling this is totally ridiculous because there's no use case that requires adding event listeners at a scale that could _ever_ be a performance concern, but anyway - http://jsperf.com/jquery-on-vs-native/3. So just 10x slower on even this - completely not performance critical and therefore nobody would bother optimising it - method.
I totally agree that jQuery is a significant improvement over the native DOM as an API, and that thinking about/profiling what your jQuery code is doing is a better approach than deciding to try to avoid jQuery whenever possible.
However, throwing away jQuery for whatever reason (as we have on the iOS-only project I've been on for the last 3 months) doesn't necessarily mean you're stuck in verbosity hell. We just tried to look for the points where it seemed most verbose/painful and wrote thin jQuery-ish wrappers around native stuff... so, for example, there's a short alias for querySelector All which gloms `Array.prototype.forEach` onto the return value, and class manipulation functions, and a handful of other things. Last time I checked, the library fits on one screen and none of the functions are longer than 4 lines.
Not necessarily the right approach for every project, but neither has it been a descent into hell.
Interestingly, I've never found event binding to be a particular pain point; the thing I'm really getting tired of is writing `e.preventDefault()`, but jQuery isn't going to save me from that anyway.
That's what Zepto was made for... the core of jQuery for modern browsers, without a bunch of the compatibility aspects of jQuery. (it's not 100% complete, but the core is compatible with jQuery) ex: jQuery 2.0 for newer desktop browsers, jQuery 1.9 for desktop and legacy, and Zepto for supported browsers... Do your testing in a webkit browser with Zepto, and it should be outward compatible with jQuery.
Nope, sorry, 9 times out of 10 the provision is theoretical and the interface is garbage. querySelector is pretty much the only one which does not suck — hence it being used as an example every single time.
* Querying or altering elements? Verbose shit.
* Binding events? Verbose shit.
* Delegating events? You've got 2 different specs, the most recent one is unimplemented and the older one is prefix-implemented everywhere (and useless as far as I know).
* Inserting elements in a DOM tree? Oh boy you're going to have a fun time manually traversing crap until you can reliably use insertBefore.
* Creating a node with text in it? You're in for 3 different statements, and that's if you're not trying to add attributes as well
* Manipulating classes? Hello broken regex search&replace. Oh you're targeting IE9 anyway? Well fuck you still, because Element#classList is IE10+.
* Playing with data-* elements? I hope you like getAttribute, because Element#dataset is MIA in MSIE.
* And bulk operations? What, you think querySelectorAll or getElementsByClass is going to return an array? Dream on, you may get something array-like in DOM4 if you're lucky. That means IE15, maybe.
Every single time I tried to get by with raw DOM, I fell back on zepto or jquery, life's too short for shit APIs and the DOM is exactly that. I don't code in raw DOM for the same reason I've stopped coding in assembly: I value my life more.
Now there are issues with jQuery, but these issues are generally that jQuery makes it easy to do the wrong thing (it's important to note that it also makes it easy to do the right thing, and improves that all the time, the "ease of doing the wrong thing" is just a side-effect of making things easier in general, the library does not specifically drive the user to the wrong thing) (except for animation maybe) e.g. keep doing noop work on empty selections, repeatedly select the same elements over and over again instead of caching the selection or not realizing you're doing a batch operation of adding a class or event on hundreds of DOM nodes in a single line.
The DOM itself does not fix this, it just makes these things so incredibly and obviously painful you look for other ways to do it to try and slightly alleviate the pain.
You get the same result out of thinking, and not blindly using jQuery.each and the like.
edits: formatting, classes manipulations, data-* attributes, matches/matchesSelector.