2

免责声明: 在 you-can't-parse-html-with-regex 盲目咒语开始之前 - 请给我怀疑的好处并将这个问题读到最后(+假设我已经知道那个 RegEx-ing HTML 将让你发疯解析 Html The Cthulhu Way )


大多数对正则表达式匹配 HTML 的抱怨来自这样一个事实,即 HTML 格式松散,正则表达式难以匹配不同的问题和用户错误 + 递归等其他一些事情。

但是 - 如果 HTML 实际上是有效的 XHTML(或更类似于 XML),它源自受控环境(不是一般的用户生成的 HTML 文档,而是例如您将在客户端模板引擎中使用的 HTML 片段模板)怎么办? ) 并且已经手动检查错误并多次验证?


让我解释一下我为什么感兴趣。我正在对 Javascript 中的不同 String2DOM 技术进行速度基准测试,并且测试了从 innerHTML、outerHTML、insertAdjacentHTML、createRange、DOMParser、doc.write(通过 iFrame)甚至是 John Riesigs HTMLtoDOM JS 库的所有内容。

我很好奇是否有更快的方法。

createElement/appendChild(+setAttribute 和 createTextNode)是在 Javascript 中创建 DOM 元素的最快方法。正则表达式是遍历大字符串的最快方法。难道这两种方法不能仍然结合起来,以可能创建一种更快的方法来将 DOMString 片段解析为 DOM 吗?

一个示例 HTML 字符串:

<div class="root fragment news">

    <div class="whitebg" data-name='Freddie Mercury'>
        <div id='myID' class="column c2">
            <h1>This is my title</h1>
            <p>Vivamus urna <em>sed urna ultricies</em> ac<br/>tempor d </p>
            <p>Mauris vel neque sit amet Quisque eget odio</p>
        </div>      

        <div class="nfo hide">Lorem <a href='http://google.com/'>ipsum</a></div>
    </div>

</div>

因此,理想情况下,代码将返回一个带有正则表达式的 documentFragment,解析 XHTML 汤并使用 createElement/appendChild (+setAttribute/createTextNode) 来填充元素。(一个类似但还不完全的例子是HTML2DOM

我(和世界其他地方)非常非常感兴趣,如果这样的东西可以在 JS 中从 DOMString 生成 DOM 中击败好的旧的 innerHTML。可以吗?

谁愿意尝试他们的知识来制作这样的东西?并在 Stackoverflow 的编年史中占据一席之地?:)


EDIT2:谁曾经盲目地对此投票 - 至少解释一下你觉得这个问题有什么问题?我对这个主题非常熟悉,提供了它背后的逻辑,并解释了这个场景的不同之处+甚至发布了一些提供类似解决方案的链接。那你呢?

4

1 回答 1

0

首先,所有以性能为导向的问题的答案都是“仅进行基准测试”。如果您想编写代码,您可以编写代码,它的性能将不言而喻。

也就是说,我将尝试根据我对 Web 浏览器行为的了解来回答您的问题,并可能为您节省一些工时。

不,自定义的 Javascript 驱动的 HTML 解析器无法“在 JS 中从 DOMString 生成 DOM 中击败旧的 innerHTML”。从理论上讲,它可能能够获得同样出色的性能,但这种结果不太可能。

原因是因为 Javascript 是一种解释性语言。一个理想的JS 解释器会将 JS 代码优化到其原生等效的浏览器 API 调用序列。因此,在最好的情况下,编写与平台原生代码等效的 JS 代码将获得相同的性能:JS 代码无法超越其原生等效代码,因为在底层,它仍然必须进行原生调用。

这里手头的任务是创建一个 DOM 树。innerHTML以下是设置元素的 时发生的情况:

JS:浏览器,给我渲染一些 HTML!这是一个 Javascript 字符串对象。

浏览器:parse_html_and_create_dom_objects()

浏览器:notify_javascript_of_dom_creation()

现在,如果您使用 Javascript 驱动解析器,会发生以下情况:

JS:scan_string_for_next_token()

JS:浏览器,在这里添加一个DOM元素!

浏览器:create_dom_object()

JS:scan_string_for_next_token()

JS:浏览器,在这里添加一个DOM元素!

浏览器:create_dom_object()

JS:浏览器,将您创建的 DOM 树附加到这个屏幕上可见的 DOM 树!

浏览器:refresh_page_view_and_notify_js()

在本机版本中,返回浏览器的一系列 JS 调用可以全部批处理并在纯预优化 C 中执行。

我认为您认为在 JS 中进行解析可能比在浏览器内部进行解析更快的原因是因为您发现某些 Web 浏览器createElement重复调用所花费的时间比设置innerHTML为块所需的时间更少。这是因为这两个调用执行的工作量不同。当您调用 时createElement,您没有进行字符串处理(没有标记化,没有词法分析)。当你打电话时innerHTML = <string>,你就是。所以是否innerHTML比一系列createElement调用快,取决于从 JS 中逐个获取元素的累积开销是否超过解析 HTML 字符串的成本。换句话说,你作弊了:你的基准测试没有测量相同数量的工作,因为调用的代码createElement必须事先知道要创建哪些元素。

解析 HTML 字符串从 JS 单独创建元素不太可能比在浏览器中同时执行这两者更快如果您确实设法编写了优于浏览器内部的 JS 代码,请将其提交给浏览器作者上游:Web 浏览器性能改进对每个人都有帮助,我相信开发人员会欣赏从嵌套解释器中获得卓越性能的讽刺意味比他们在翻译之外所能达到的最好水平。

于 2012-06-23T08:46:32.803 回答