重学前端-总结:11 、浏览器:一个浏览器是如何工作的?(阶段二)

重学前端-总结:11 、浏览器:一个浏览器是如何工作的?(阶段二)

前言

上节内容

览器使用 HTTP 协议或者 HTTPS 协议,向服务1端请求页面的过程。

本节内容:个过程:

如何解析请求回来的 HTML 代码?

DOM 树又是如何构建的?

字符流-》状态机=》词token=》栈=》dom树

解析代码

带着问题去学习:
HTTP 的 Response 的 body怎么处理的?

HTML 的结构不算太复杂,我们日常开发需要的 90% 的“词”(指编译原理的术语 token,表示最小的有意义的单元),种类大约只有标签开始、属性、标签结束、注释、CDATA 节点几种。

实际上有点麻烦的是,由于 HTML 跟 SGML 的千丝万缕的联系,我们需要做不少容错处理。“<?”和“<%”什么的也是必须要支持好的,报了错也不能吭声。

词(token)是如何被拆分的

标准的标签,会被如何拆分:

<p class="a">text text text</p>

代码依次拆成词(token):

  • <p“标签开始”的开始;
  • class=“a” 属性;
  • > “标签开始”的结束;
  • text text text 文本;
  • 标签结束。

浏览器工程师处理标签方法:使用状态机把字符流解析成词(token)

状态机原理

绝大多数语言的词法部分都是用状态机实现的。那么我们来把部分词(token)的解析画成一个状态机看看:
重学前端-总结:11 、浏览器:一个浏览器是如何工作的?(阶段二)

真正完整的 HTML 词法状态机,比我们描述的要复杂的多。更详细的内容,你可以参考HTML 官方文档,HTML 官方文档规定了 80 个状态

状态机的初始状态,我们仅仅区分 “< ”和 “非 <”:

  • 如果获得的是一个非 < 字符,那么可以认为进入了一个文本节点;
  • 如果获得的是一个 < 字符,那么进入一个标签状态。

不过当我们在标签状态时,则会面临着一些可能性。

  • 比如下一个字符是“ ! ” ,那么很可能是进入了注释节点或者 CDATA 节点。

  • 如果下一个字符是 “/ ”,那么可以确定进入了一个结束标签。

  • 如果下一个字符是字母,那么可以确定进入了一个开始标签。

  • 如果我们要完整处理各种 HTML 标准中定义的东西,那么还要考虑“ ? ”“% ”等内容。

用状态机做词法分析,其实正是把每个词的“特征字符”逐个拆开成独立状态,然后再把所有词的特征字符链合并起来,形成一个联通图结构。

具体处理过程,学习编译原理知识。

构建 DOM 树

使用的栈正是用于匹配开始和结束标签的方案构建 DOM 树:

  • 栈顶元素就是当前节点;
  • 遇到属性,就添加到当前节点;
  • 遇到文本节点,如果当前节点是文本节点,则跟文本节点合并,否则入栈成为当前节点的子节点;
  • 遇到注释节点,作为当前节点的子节点;
  • 遇到 tag start 就入栈一个节点,当前节点就是这个节点的父节点;
  • 遇到 tag end 就出栈一个节点(还可以检查是否匹配)。

我在文章里面放了一个视频,你可以点击查看用栈构造 DOM 树的全过程。

当我们的源代码完全遵循 xhtml(这是一种比较严谨的 HTML 语法)时,这非常简单问题,然而 HTML 具有很强的容错能力,奥妙在于当 tag end 跟栈顶的 start tag 不匹配的时候如何处理。

于是,这又有一个极其复杂的规则,幸好 W3C 很贴心地把全部规则都整理地很好,我们只要翻译成对应的代码就好了,以下这个网站呈现了全部规则。你可以点击查看。
http://www.w3.org/html/wg/drafts/html/master/syntax.html#tree-construction

重学前端-总结:11 、浏览器:一个浏览器是如何工作的?(阶段二)