> So you are saying that Array.from(querySelectorAll) gets you there? What are you missing then?
Array.from adds friction. The need to wrap querySelector in null checks adds friction. The fact that they are not composable in any way, shape, or form, with any DOM methods (and that DOM methods are not composable) adds friction.
jQuery was the fore-runner of fluid interface design. Nothing in the DOM before, then, or since ever thought about it. Even the new APIs are all the same 90s Java-style method calls with awkward conversions and workarounds to do anything useful.
I agree that DOM lists not being real arrays is a pita. I can understand why for getElementBy* methods which return live lists, but it's less clear for those methods returning fixed lists.
But to me, these are minor inconveniences and habits. A thin wrapper can get you there easily if you care enough. I personally dislike this array/element confusion that jQuery adds.
> A thin wrapper can get you there easily if you care enough
But that's more and more friction. A wrapper here, a wrapper there, and if here, a try/catch there. At one point you are reinventing significant chunks of jQuery
- its custom selector parser (because it had it before querySelector and is not totally compatible with it)
- its abstraction to iron out browser differences (old IE vs standard, notably) that's not relevant anymore
- its own custom (DOM) event management
- its implementation of methods that are now standard (ajax & trim for instance)
I recognize that the DOM API could be better, and comes with friction. Back then, ironing out the browser differences and its selector feature were killer features of jQuery. Today, I do not think the quirks of the DOM API warrant importing a library like jQuery.
¹ but indeed, very lightweight compared to modern frameworks like Angular, React and Vue, with all the ecosystem which comes with each of them (react-router, redux, etc).
quack quack quack... why reinvent the wheel, why not adopt a good, working system, why the need to do everything in a complicated way? give resig a big black suitcase full of money and implement his complexity reduction framework called jQuery into the standard. And fire the standards guys in the process, because what they do is shit. they most presumably never worked extensively with the shit they produce.
I'm not advocating complicated, I'm advocating lightweight. We should not be importing libraries left and right for our convenience to the detriment of the user.
If you are going to use many features of jQuery, then it makes sense to use it, but if it's only a matter of writing one or a with wrappers, then jQuery is overkill.
I don't have a strong opinion on the proposal described in the article.
You don't need Array.from if you are using `for (const x of document.querySelectorAll(selector) { }` loops anyway or have a library like IxJS handy.
ES2025 added map, filter, flatMap, reduce, forEach, and several other methods to all iterators (including NodeList directly, I believe, but definitely its entries(), keys(), values(), if not) [1]. It'll be a year or two at current pace before that is "widely accepted baseline" in browsers, but it's great progress on these sorts of complaints.
You missed [Symbol.iterator] as a public method. I prefer the aesthetics of for/of over forEach in most cases, but it's as much personal preference as anything.
I did briefly forget the distinction between Iterable (has [Symbol.iterator]) and Iterator (the thing [Symbol.iterator]() returns). You can use the Iterator helpers "directly" on the NodeList with `someNodeList[Symbol.iterator]().map(…)` or `Iterator.from(someNodeList).map(…)`. There are advantages to that over `Array.from` but not many advantages over `someNodeList.entries().map(…)`.
(I partly forgot because I assumed MDN hadn't been updated with the new Iterator helpers, but of course it has [1], they are marked as "Baseline March 2025" [all browsers updated since March 2025 support them] and there is a lot of green in the browser compatibility tables. caniuse suggests Iterator.prototype.map is ~84% globally available.)
[Symbol.iterator] is more the for/of API (protocol, more accurately) than a DOM API. It's an improvement today that the DOM APIs pick up niceties like direct [Symbol.iterator] in addition to Iterator methods like entries().
It's nice that there is syntax sugar for [Symbol.iterator] in both for/of and also the spread operator/deconstruction/rest operator (things like [...someNodeList] and const [item1, item2, ...rest] = nodeList).
In theory, the only missing piece is syntax sugar for Iterator.from() if you wanted to direct chain any iterable to the iterator helperrs. But in practice, that's also part of why the explicit iterator methods like entries() already exist and those are surprisingly well implemented (and have been for a while), including on NodeList.