I made a remark about this on Twitter, but - now that I think about it - it’s probably worth repeating here. The essence of the problem here is that selection is not a homomorphism, and that is leading to confusion. A homomorphism is somewhat of a “structure preserving” operation. For example, I have
length [a,b] = length ([a] + [b]) = 2
length satisfies the homomorphism property, as
length ([a] + [b]) = length [a] + length [b] == 2
The main source of API confusion comes because querySelectorAll is not a homomorphism, though intuitively we expect it to be (I would consider that an API bug).
Being aware of this basic mathematical property goes a long way when it comes to designing APIs.
Wow, I was very surprised by the way querySelector and querySelectorAll work, despite using these APIs frequently.
Almost always, when I reach for el.querySelector (as opposed to document.querySelector), all I need is a simple (generally one class even) selector for an element’s children.
The real behaviour under normal use is consistent with the expected result from the wrong mental model. Before reading the article I was very confident that I understood the API, because I’ve never been confronted with a case that broke my mental model.
Yes, this surprised me for sure. Glad to have learned it.