2014-09-07 3 views
6

Всем известно, какие DOM-селекторы, такие как document.getElementByID(...) и document.querySelector(...), делают и как вы можете использовать его с классами, атрибутами, идентификатором и т. Д.Как работает querySelector под капотом?

Но я не смог найти, как это работает под капотом (я могу найти perf test comparisons, но меня интересует теория). Я знаю, что страница html загружается, анализируется браузером и создается дерево DOM. Но как каждый из селекторов пересекает дерево DOM, чтобы найти элементы.

Я посмотрел на spec for parsing algorithm и читать очень приятно explanation how Browsers work, но и дает превосходное объяснение о том HTML, CSS анализе и визуализации потока не дает объяснения, как каждый из этих селекторов траверсов этого дерева, чтобы найти элементы.

Я полагаю, что для того, чтобы найти что-то вроде .black или span он должен пройти все дерево, но найти #id можно обход некоторых дополнительной структуры данных, и, таким образом, что делает его гораздо быстрее. Пожалуйста, не пишите свои предположения, я ищу конкретные знания с резервным копированием до спецификации или реализации в некоторых браузерах.

+0

Я думаю, что это было бы лучше спросить на http://programmers.stackexchange.com – spender

+7

Это деталь реализации и будет отличаться в зависимости от того, какой движок вы используете. Если вы хотите узнать, вам нужно будет прочитать исходный код различной реализации. См. Http://en.wikipedia.org/wiki/List_of_ECMAScript_engines как отправную точку. – slashingweapon

+0

@slashingweapon На самом деле я так не думаю. Это довольно простая функция, и, скорее всего, я буду реализован по-настоящему похожим в основных браузерах. –

ответ

6

Осмотр Firefox's source и чтение the related documentation помогут получить начальное понимание.
После того, как документ извлечен, он передается в синтаксический анализатор (см.: /mozilla/parser/html/), который будет пережевывать документ и генерировать дерево данных. Центральные части анализатора написаны на Java (/mozilla/parser/html/javasrc/), а затем переведены на C++ для построения, поэтому будьте готовы хорошо провести время, когда вы захотите прочитать остальную часть источника.

Глядя на источник парсера (/mozilla/parser/html/javasrc/TreeBuilder.java), а именно отрывок из функции startTag:

1579   if (errorHandler != null) { 
1580    // ID uniqueness 
1581    @IdType String id = attributes.getId(); 
1582    if (id != null) { 
1583     LocatorImpl oldLoc = idLocations.get(id); 
1584     if (oldLoc != null) { 
1585      err("Duplicate ID \u201C" + id + "\u201D."); 
1586      errorHandler.warning(new SAXParseException(
1587        "The first occurrence of ID \u201C" + id 
1588        + "\u201D was here.", oldLoc)); 
1589     } else { 
1590      idLocations.put(id, new LocatorImpl(tokenizer)); 
1591     } 
1592    } 
1593   } 

Токарный внимание на линии 1590 и имея в виду, что ранее в том же файле, который мы имеем:

459  private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>(); 

Мы можем видеть, что идентификаторы узлов хранятся в простой карте хэша. Выяснение того, как обрабатываются классы, - это упражнение, оставленное читателю.

Различные методы DOM, например document.getElementByID(...), подключены к этой карте хэша через код клея и множество иерархии объектов, см. "How is the web-exposed DOM implemented?" on ask.mozilla.org.

+2

Отличный ответ! –

Смежные вопросы