1

Reading through some js-files loaded in the background of a site, I came across this construct:

var foo = (document.querySelector(".some-selector"), 
document.querySelectorAll(".some-selector > ul > li"));
Array.prototype.forEach.call(foo, ...);

The call to querySelector() seems obsolete, but going by the code and the source of this script, I don't get the feeling that this was a mistake, or that they meant [...] instead of (...). The code was minified, but not obfuscated; to me this seems intentionally, but I don't get the point.

My best guesses are that either, the call to querySelector() somehow speeds up the subsequent call to querySelectorAll() or that this is some kind of browser hack. But I could not find anything related to this construct yet.

Does anyone here know what this is about, or point me in the right direction?

Sreekanth
  • 3,110
  • 10
  • 22
Thomas
  • 11,958
  • 1
  • 14
  • 23
  • The minified code isn't the *source* code. I'd look at the source code to see what this came from, but I wouldn't be surprised if it was just a mistake. For better performance, the code would have called `querySelectorAll` on the `.some-selector` element (assuming there's just one such parent, or maybe just left off the `querySelector` entirely, not sure what the internal algorithm uses for iteration / match testing) – CertainPerformance Jan 02 '20 at 04:15
  • Some sites (like Stack Overflow) serve minified code, but also have their source code available, hopefully you're lucky enough to be on one of those sites – CertainPerformance Jan 02 '20 at 04:17
  • `For better performance, the code would have called querySelectorAll on the .some-selector element` no, `" > ul > li"` is not a valid selector. No luck with the non-minified code. – Thomas Jan 02 '20 at 04:44
  • Thomas `document.querySelector('.some-selector').querySelector(".some-selector > ul > li")` would work too, but contrarily to what one may first think, it's actually faster to go from document, because the selector has to go from the root anyway, exactly to make this case work... cc @CertainPerformance – Kaiido Jan 02 '20 at 06:01
  • For the question at hand though... I never heard of such an hack, and if it did have any *good* influence in a certain version of an engine with a certain structure of document, I wouldn't bet it holds true in any other. – Kaiido Jan 02 '20 at 06:03
  • @Kaiido I was thinking that, if `querySelectorAll` essentially iterates over every element in the document and checks if it `.matches`, if there's just one `.some-selector`, then using `querySelector` first would stop the expensive full-document search there, and then a `qSA` on that element to only search *its* children would be faster. Does that sound right? (don't know if there's *actually* just one `.some-selector` element here though) – CertainPerformance Jan 02 '20 at 06:09
  • @CertainPerformance that would be assuming the engine keeps in memory the results of previous requests right? Could actually happen, but once again, I never heard of this... – Kaiido Jan 02 '20 at 06:13
  • @Kaiido I mean. if you call the `qSA` on the element you just selected, not on the `document` – CertainPerformance Jan 02 '20 at 06:13
  • That's quite old, but since it's a flaw in the specs, I think it still holds: https://stackoverflow.com/questions/32430923/why-document-queryselector-is-more-efficient-than-element-queryselector But performances of selectors will always depend on the document's structure anyway... – Kaiido Jan 02 '20 at 06:28

1 Answers1

-1

This is one of the peculiarity of comma(,) operator.

let me explain what it means,

var x = (2+3, 4+5, 6+7);
console.log(x); // 13

It is used to cascade multiple statements into a single one. From above code, we can see that the output is 13 and not 7 or 9. This is because, javascript executes all the statements within the paranthesis, but only the result of the last statement is returned. Hence, "x" has "13" as its value.

Coming to the problem at hand,

var foo = (document.querySelector(".some-selector"), 
document.querySelectorAll(".some-selector > ul > li"));
Array.prototype.forEach.call(foo, ...);

the first statement is executed but it's result is not returned. Hence, the value of "foo" will be the result of second statement. Later looping through the resultant array from the second statement.

For more information click here.

  • The question is not what the comma operator does - the question is what purpose there would be of the seemingly-unused expression from `querySelector`. Your answer doesn't really have anything to do with the question. – CertainPerformance Jan 02 '20 at 06:56