为什么是文件。写作被认为是“不好的做法”?

我知道document.write被认为是不好的做法;我希望编写一个理由列表,提交给第三方供应商,说明他们为什么不应该在分析代码的实现中使用document.write

请包括你的理由声称document.write作为一个坏的做法下面。

206950 次浏览

实际上,document.write本身没有任何问题。问题是它很容易被误用。严重,甚至。

对于提供分析代码的供应商(如谷歌analytics)来说,这实际上是他们分发此类代码片段的最简单方法

  1. 它使脚本保持较小
  2. 他们不必担心重写已经建立的onload事件或包括必要的抽象来安全地添加onload事件
  3. 它非常兼容

在我看来,只要你不尝试在文档加载后使用它document.write本身并不是邪恶的。

它覆盖了页面上的内容,这是最明显的原因,但我不认为它“坏”。

除非使用JavaScript创建整个文档,否则它没有多大用处,在这种情况下,您可以从document.write开始。

即便如此,在使用文档时,您并没有真正利用DOM。写——你只是在向文档中倾倒一团文本,所以我认为这是糟糕的形式。

我认为最大的问题是任何通过文档编写的元素。写被添加到页面元素的末尾。这很少是现代页面布局和AJAX所期望的效果。(您必须记住DOM中的元素是临时的,脚本何时运行可能会影响其行为)。

最好在页面上设置一个占位符元素,然后操作它的innerHTML。

我能想到的是:

  1. document.write需要在页面加载或主体加载中使用。因此,如果您想在任何其他时间使用脚本来更新您的页面内容文档。写作几乎毫无用处。

  2. 从技术上讲,document.write只更新HTML页面,不更新XHTML/XML。IE似乎对这个事实很宽容,但其他浏览器不会。

http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite

一些比较严重的问题:

  • 文档。write(因此DW)在XHTML中不起作用

  • DW不直接修改DOM,防止进一步的操作 (试图找到这一点的证据,但这是最好的情景)

  • 在页面加载完成后执行的DW将覆盖该页,或写入新页面,或不工作

  • DW在遇到的地方执行:它不能在给定的节点上进行注入

  • DW有效地编写序列化文本,这不是DOM概念上的工作方式,而且是一种容易产生错误的方法。innerHTML也有同样的问题)

最好使用安全和DOM友好的DOM操作方法

它使用XML呈现来分割页面(如XHTML页面)。

最好的:一些浏览器切换回HTML渲染,一切工作正常。

可能的:某些浏览器在XML呈现模式中禁用document.write()函数。

最糟糕的:某些浏览器在使用document.write()函数时会触发XML错误。

正方观点:

  • 这是从外部(到您的主机/域)脚本嵌入内联内容的最简单方法。
  • 你可以覆盖一个frame/iframe中的全部内容。在更现代的Ajax技术广泛可用之前(1998-2002),我经常在菜单/导航部分使用这种技术。

反对:

  • 它序列化渲染引擎,直到加载外部脚本,这可能比内部脚本花费更长的时间。
  • 它通常以这样一种方式使用,即将脚本放在内容中,这被认为是糟糕的形式。

这是我的两便士价值,一般来说,你不应该使用document.write来做繁重的工作,但有一个实例它肯定是有用的:

http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html

我最近在尝试创建AJAX滑块库时发现了这一点。我创建了两个嵌套的div,并用JS将width/heightoverflow: hidden应用到外层的<div>。这样,在浏览器禁用JS的情况下,div将浮动以容纳图库中的图像-一些漂亮的优雅降级。

问题是,与上面的文章一样,这种JS劫持CSS直到页面加载后才开始,导致div加载时出现短暂的闪光。所以我需要写一个CSS规则,或包括一个表,作为页面加载。

显然,这在XHTML中行不通,但由于XHTML似乎是一个死鸭(并且在IE中呈现为标签汤),可能值得重新评估您对DOCTYPE的选择…

它可以阻止你的页面

document.write只在页面加载时工作;如果在页面加载完成后调用它,它将覆盖整个页面。

这实际上意味着你必须从一个内联脚本块中调用它——这将阻止浏览器处理接下来页面的部分内容。直到写入块完成,脚本和图像才会被下载。

document.write的另一个合法用法来自HTML5 Boilerplate index . html示例。

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>

我还见过使用json2.js JSON解析/stringify polyfill (IE7及以下版本需要)的相同技术。

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>

可以将document.write()(和. innerhtml)看作是对源代码字符串求值。这对于许多应用程序来说非常方便。例如,如果您从某个源获取HTML代码作为字符串,那么只需“计算”它就很方便。

在Lisp的上下文中,DOM操作就像操作一个列表结构,例如通过执行以下操作创建列表(橙色):

(cons 'orange '())

而document.write()就像求值一个字符串,例如通过这样求值一个源代码字符串来创建一个列表:

(eval-string "(cons 'orange '())")

Lisp还具有使用列表操作创建代码的非常有用的能力(例如使用“DOM样式”创建JS解析树)。这意味着你可以使用“DOM样式”构建一个列表结构,而不是“字符串样式”,然后运行该代码,例如:

(eval '(cons 'orange '()))

如果您实现编码工具,例如简单的实时编辑器,那么能够快速计算字符串是非常方便的,例如使用document.write()或. innerhtml。在这个意义上,Lisp是理想的,但你也可以用JS做非常酷的事情,很多人都在做,比如http://jsbin.com/

  • document.write是一个不好的做法的一个简单原因是,你无法想出一个你找不到更好的替代方案的场景。
  • 另一个原因是您正在处理字符串而不是对象(这是非常原始的)。
  • 它只附加到文档中。
  • 它没有例如MVC(模型-视图-控制器)模式的美丽。
  • 使用jQuery ajax +angularJS来表示动态内容要强大得多。

文件的缺点。写作主要取决于这3个因素:

)实现

write()主要用于在需要内容时立即将内容写入屏幕。这意味着它发生在任何地方,要么在JavaScript文件中,要么在HTML文件中的脚本标记中。由于script标记被放置在这样的HTML文件中的任何地方,在与网页中的HTML交织在一起的脚本块中使用document.write()语句是一个坏主意。

b)呈现

设计良好的代码通常会接受任何动态生成的内容,将其存储在内存中,在它最终出现在屏幕上之前,在它通过代码时一直对其进行操作。因此,重申上一节中的最后一点,原地呈现内容可能比可能依赖的其他内容呈现得更快,但对于反过来要求呈现内容以进行处理的其他代码来说,它可能不可用。为了解决这个难题,我们需要摆脱document.write(),并以正确的方式实现它。

c)不可能的操作

一旦写好了,就结束了。如果不进入DOM,我们就不能返回去操作它。

Chrome可能会阻止document.write插入脚本在某些情况下。当这种情况发生时,它将在控制台中显示以下警告:

解析器阻塞,跨原点脚本,…,通过 document . write。这可能会被浏览器阻止,如果设备

.网络连通性差

引用:

根据Google-Chrome开发工具的灯塔审计所做的分析,

对于连接速度较慢的用户,通过document.write()动态注入的外部脚本可以将页面加载延迟数十秒。

enter image description here

浏览器违反

.write被认为是浏览器违规,因为它会停止解析器渲染页面。解析器接收到文档正在被修改的消息;因此,它会被阻塞,直到JS完成它的进程。只有在这个时候,解析器才会恢复。

性能

使用这种方法的最大后果是降低性能。浏览器需要更长的时间来加载页面内容。加载时间的不良反应取决于写入文档的内容。如果你在DOM中添加一个<p>标记,而不是将一个包含50个左右引用的数组传递给JavaScript库,你不会看到太大的区别(我在工作代码中看到过这种情况,导致11秒的延迟——当然,这也取决于你的硬件)。

总而言之,如果可以的话,最好避免使用这种方法。

更多信息见干预document.write()

我不认为使用文档。写作根本就是一种糟糕的习惯。简单地说,对于没有经验的人来说,这就像一个高压。如果用错了,你就会被煮熟。有许多开发人员至少使用过一次这种或其他危险的方法,但他们从未真正深入研究过自己的失败。相反,当出现问题时,他们只是跳出来,使用更安全的东西。正是这些人对所谓的“坏习惯”做出了这样的声明。

这就像格式化硬盘驱动器,当你只需要删除几个文件,然后说“格式化驱动器是一个坏习惯”。