Какая разница между живой и не живой коллекцией в Javascript-селекторах?

Как я могу узнать, в чем разница между живой, а не живой коллекцией.

Согласно моим исследованиям:

A live: когда изменения в DOM отражаются в коллекции. Содержимое изменяется после изменения node.

A Не в сети: когда любые изменения в DOM не влияют на содержимое коллекции.

document.getElementsByClassName() - это HTMLCollection и является живым.

document.getElementsByTagName() - это HTMLCollection и является живым.

document.getElementsByName() - это NodeList и находится в режиме реального времени.

document.querySelectorAll() является NodeList и не является живым.

Почему document.querySelectorAll не работает?

Я знаю, что:

HTMLCollection содержит только узлы Elements NodeList содержит узлы элементов и текстовые узлы.

2 ответа

Эти

document.getElementsByClassName()
document.getElementsByTagName()
document.getElementsByName()

являются живыми, потому что они являются наблюдателями внутренних коллекций, поддерживаемых двигателями. Это техническое обслуживание строго не требуется, но его легко достичь.

document.querySelectorAll()

не является живым, потому что результат вычисляется каждый раз, когда вы его запрашиваете. Обслуживание живой коллекции слишком дорого, так как каждая модификация (содержимое, атрибуты, классы) DOM в этом случае потребует переоценки каждого элемента в коллекции - O(N*M) задача, где N - количество всех элементов в DOM (наихудший случай) и M количество активных коллекций querySelectorAll().


Из DOM spec

Коллекция представляет собой объект, который представляет списки узлов DOM. <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> может быть как живым, так и статическим. Если не указано иное указано <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> должно быть <a href="http://www.w3.org/TR/dom/#concept-collection-live" rel="nofollow noreferrer" target="_blank">live</a>.

Если <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> <a href="http://www.w3.org/TR/dom/#concept-collection-live" rel="nofollow noreferrer" target="_blank">live</a>, то атрибуты и методы на этот объект должен работать с фактическими базовыми данными, а не с моментальным снимком данных.

Когда создается <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a>, фильтр и корень связаны с ним.

<a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> затем представляет собой представление поддерева, внедренного в <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> root, содержащий только узлы, которые соответствуют данному фильтр. Вид является линейным. В отсутствие конкретных требований к напротив, узлы в <a href="http://www.w3.org/TR/dom/#concept-collection" rel="nofollow noreferrer" target="_blank">collection</a> должны быть отсортированы в <a href="http://www.w3.org/TR/dom/#concept-tree-order" rel="nofollow noreferrer" target="_blank">порядок дерева</a>.

Причины, по которым querySelectorAll возвращает статический NodeList, могут иметь возможность разрешать более сложные селекторы.

Например, селектор L4 может вводить такие вещи, как псевдо-класс :has(). Вероятно, поскольку он не может быть реализован с разумной производительностью, он будет доступен только в querySelectorAll, но не в таблицах стилей.

Если коллекция, возвращаемая querySelectorAll, была вживую, тогда эти сложные селекторы нужно было бы пересчитать много раз, и это было бы так дорого.

licensed under cc by-sa 3.0 with attribution.