Это медленно по разным причинам. Наиболее очевидным является тот факт, что никто не использует его так просто, гораздо меньше времени было потрачено на его оптимизацию. Другая проблема заключается в массовом повторном входе, каждый узел должен вызывать JS и запускать функцию фильтра.
Если вы посмотрите на ревизию 3 эталонного теста , вы обнаружите, что я добавил повторную реализацию того, что делает итератор, используя getElementsByTagName("*")
, а затем запустил идентичный фильтр для этого. Как показывают результаты, это значительно быстрее. Идет JS -> C ++ -> JS медленно.
Полная фильтрация узлов в JS (случай getElementsByTagName
) или C ++ (случай querySelectorAll
) выполняется намного быстрее, чем повторное пересечение границы.
Обратите внимание, что сопоставление селекторов, используемое querySelectorAll
, сравнительно разумно: оно выполняет сопоставление справа налево и основано на предварительно вычисленных кэшах (большинство браузеров перебирают кэшированный список всех элементов с классом "класс", проверьте, является ли он элементом a
, а затем проверьте, является ли родительский элемент div
), и, следовательно, они даже не будут перебирать весь документ.
Учитывая, что, когда использовать NodeIterator? По крайней мере, в JavaScript. В таких языках, как Java (несомненно, это основная причина, по которой существует интерфейс с именем NodeIterator), он, скорее всего, будет таким же быстрым, как и все остальное, так как тогда ваш фильтр будет на том же языке, что и фильтр. Кроме того, единственный раз, когда это имеет смысл, это в языках, где использование памяти для создания объекта Node намного больше, чем внутреннее представление Node.