Sal*_*ali 9 javascript dom internals selectors-api
每个人都知道DOM选择器喜欢document.getElementByID(...)和document.querySelector(...)做什么,以及如何将它与类,属性,id等一起使用.
但我无法找到它是如何工作的(我可以找到性能测试比较,但我对理论感兴趣).我知道html页面是加载的,由浏览器解析并构建DOM树.但是每个选择器如何遍历DOM树以找到元素.
我已经看了一个解析算法的规范并阅读了很好的解释浏览器是如何工作的,但它也提供了关于HTML,CSS解析和渲染流程的优秀解释,它没有解释每个选择器如何遍历这个树来查找元素.
我假设为了找到类似的东西.black或者span它需要遍历整个树,但是发现#id它可能会遍历一些额外的数据结构,从而使它更快.请不要写下您的假设,我正在寻找具备备份到规范或在某些浏览器中实现的具体知识.
检查Firefox的来源并阅读相关文档将有助于获得一些初步见解.
获取文档后,它将传递给解析器(请参阅:/ 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 }
Run Code Online (Sandbox Code Playgroud)
将注意力转向第1590行,并记住我们在同一文件中的早期版本:
459 private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>();
Run Code Online (Sandbox Code Playgroud)
我们可以看到节点ID保存在一个简单的哈希映射中.查看如何处理类是一个留给读者的练习.
例如document.getElementByID(...),不同的DOM方法通过粘合代码和过多的对象层次结构连接到此哈希映射,请参阅"如何实现Web暴露的DOM?" 在ask.mozilla.org上.