Why is document.write considered a “bad practice”?
我知道
请在下面说明您将
一些更严重的问题:
document.write(此后dw)在xhtml中不起作用
dw不直接修改dom,防止进一步的操作(尝试寻找证据,但最好是情境性的)页面加载完成后执行的dw将覆盖页面,或写入新页面,或不工作
dw在遇到时执行:它不能在给定节点点插入
DW有效地编写序列化文本,这不是DOM概念上的工作方式,而且是创建bug的简单方法(.innerhtml有相同的问题)。
更好地使用安全且对dom友好的dom操作方法
从本质上来说,
对于提供分析代码的供应商(如Google Analytics),这实际上是他们分发此类代码片段的最简单方法。
在我看来,只要你在加载文档后不尝试使用它,
1 2 3 | <!-- 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"> window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>') |
我还看到了使用json2.js json parse/stringify polyfill的相同技术(IE7及以下版本需要)。
1 | window.JSON || document.write('<script src="json2.js"><\/script>') |
它会阻塞你的页面
这实际上意味着您必须从一个内联脚本块调用它——这将阻止浏览器处理后面的页面部分。在写入块完成之前,将不会下载脚本和图像。
赞成的意见:
- 这是从外部(到主机/域)脚本嵌入内联内容的最简单方法。
- 您可以覆盖frame/iframe中的整个内容。在更现代的Ajax技术广泛应用之前(1998-2002年),我经常将这种技术用于菜单/导航片段。
反对的论点:
- 它将渲染引擎序列化为暂停,直到加载所述外部脚本为止,这可能比内部脚本花费更长的时间。
- 它的使用方式通常是将脚本放在内容中,这被认为是不好的形式。
这是我的两个价值观,一般来说,你不应该使用
http://www.quirksmode.org/blog/archives/2005/06/three_javacrip_1.html
我最近在尝试创建Ajax滑块库时发现了这个问题。我创建了两个嵌套的div,并将
事情是,正如上面的文章一样,JS对CSS的劫持直到页面加载后才开始,导致加载DIV时出现短暂的闪烁。所以我需要编写一个CSS规则,或者在页面加载时包含一个工作表。
显然,这在XHTML中不起作用,但是由于XHTML看起来像是一个死鸭子(并且在IE中呈现为标签汤),所以可能值得重新评估您对doctype的选择……
它使用XML呈现(如XHTML页面)来断开页面。
最佳:一些浏览器切换回HTML渲染,一切正常。
可能:某些浏览器在XML呈现模式下禁用document.write()函数。
最糟糕的是:每当使用document.write()函数时,某些浏览器都会引发XML错误。
它覆盖页面上的内容,这是最明显的原因,但我不会称之为"坏"。
它没有多大用处,除非您使用javascript创建整个文档,在这种情况下,您可以从document.write开始。
即使如此,在使用document.write时,您并没有真正利用DOM——您只是在向文档中转储一块文本,所以我认为这是一种糟糕的形式。
从我的头顶上:
从技术上讲,
http://www.w3.org/markup/2004/xhtml常见问题解答docwrite
Chrome可能会阻止在某些情况下插入脚本的
A Parser-blocking, cross-origin script, ..., is invoked via
document.write. This may be blocked by the browser if the device has
poor network connectivity.
参考文献:
- 这篇关于developers.google.com的文章更详细。
- https://www.chromestatus.com/feature/5718547946799104
基于google chrome dev tools的灯塔审计分析
可以将document.write()(和.innerhtml)看作是对源代码字符串的评估。这对于许多应用程序来说非常方便。例如,如果您从某个源代码中得到了作为字符串的HTML代码,那么只需"评估"它就很方便了。
在Lisp上下文中,DOM操作类似于操作列表结构,例如,通过执行以下操作创建列表(橙色):
1 | (cons 'orange '()) |
和document.write()类似于对字符串进行计算,例如,通过对源代码字符串进行这样的计算来创建一个列表:
1 | (eval-string"(cons 'orange '())") |
Lisp还具有使用列表操作创建代码的非常有用的能力(比如使用"dom样式"创建JS解析树)。这意味着您可以使用"dom样式"而不是"字符串样式"构建列表结构,然后运行该代码,例如:
1 | (eval '(cons 'orange '())) |
如果实现了编码工具(如简单的实时编辑器),那么能够快速计算字符串非常方便,例如使用document.write()或.innerhtml。从这个意义上讲,Lisp是理想的,但是你也可以在JS中做一些非常酷的事情,很多人都在这样做,比如http://jsbin.com。/
document.write 是一个坏做法的一个简单原因是你不能想出一个你找不到更好的替代方案的方案。- 另一个原因是您处理的是字符串而不是对象(它非常原始)。
- 它只附加到文档。
- 例如,它没有MVC(模型-视图-控制器)模式的美。
- 使用Ajax+jQuery或AngularJS呈现动态内容要强大得多。
浏览器冲突
采用这种方法的最大后果是性能降低。浏览器加载页面内容需要更长时间。加载时间的不良反应取决于写入文档的内容。如果您向DOM添加一个
标记,而不是向JavaScript库传递一个包含50个引用的数组(我在工作代码中看到过这种情况,会导致11秒的延迟——当然,这也取决于您的硬件),那么您不会看到太大的不同。
总之,如果你能帮助的话,最好避开这种方法。
有关详细信息,请参阅Interventing against document.write()。
document.write的缺点主要取决于以下三个因素:
a)实施
document.write()主要用于在需要内容时立即将内容写入屏幕。这意味着它发生在任何地方,无论是在JavaScript文件中,还是在HTML文件中的脚本标记中。由于脚本标记被放置在这样一个HTML文件中的任何位置,所以最好将document.write()语句放在脚本块内,这些脚本块与网页内的HTML交织在一起。
b)渲染
通常,设计良好的代码将获取任何动态生成的内容,将其存储在内存中,并在代码通过时继续操作,直到最终输出到屏幕。因此,为了重申上一节中的最后一点,就地呈现内容可能比可能依赖的其他内容呈现得更快,但其他代码可能无法使用就地呈现内容,而这些代码反过来又要求呈现内容进行处理。为了解决这个难题,我们需要去掉document.write()并以正确的方式实现它。
c)不可能操纵
一旦写好了,它就结束了。如果不攻入DOM,我们就不能回去操纵它。
我认为最大的问题是通过document.write编写的任何元素都会添加到页面元素的末尾。在现代页面布局和Ajax中,这很少是需要的效果。(您必须记住,DOM中的元素是临时的,脚本运行时可能会影响其行为)。
最好在页面上设置一个占位符元素,然后操作它的innerhtml。