为什么在用document.write()写入时为它分割<script>标签?

为什么一些网站(或给予客户端JavaScript代码的广告客户)采用了在document.write()调用中拆分<script>和/或</script>标记的技术?

我注意到亚马逊也这样做,例如:

 <script type='text/javascript'> if (typeof window['jQuery'] == 'undefined') document.write('<scr'+'ipt type="text/javascript" src="http://z-ecx.images-amazon.comhttp://img.dovov.comG/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></sc'+'ript>'); </script> 

</script>必须被分解,否则它会过早地结束封装的<script></script>块。 真的,它应该被分割在</ ,因为根据SGML,脚本块被终止标记打开(ETAGO)序列(即</ )所终止 :

虽然STYLE和SCRIPT元素使用CDATA作为其数据模型,但对于这些元素,CDATA必须以不同的方式由用户代理处理。 标记和实体必须被视为原始文本并按原样传递给应用程序。 字符序列“ </ ”(end-tag open delimiter)的第一次出现被视为终止元素内容的结尾。 在有效的文档中,这将是元素的结束标记。

但实际上,浏览器只能在实际的</script>closures标签上结束parsingCDATA脚本块。

在XHTML中,脚本块没有这样的特殊处理,所以它们中的任何< (或& )字符都必须&escaped; 就像其他任何元素一样。 然而,那些将XHTMLparsing为老派HTML的浏览器会感到困惑。 有涉及CDATA块的解决方法,但最简单的方法就是避免使用这些字符。 编写脚本元素的一种更好的方式是使用任何一种types的parsing器都可以:

 <script type="text/javascript"> document.write('\x3Cscript type="text/javascript" src="foo.js">\x3C/script>'); </script> 

我认为是为了防止浏览器的HTMLparsing器解释<script>,主要是</ script>作为实际脚本的结束标记,但我不认为使用document.write是评估脚本块,为什么不使用DOM …

 var newScript = document.createElement("script"); ... 

这里是我想要生成一个脚本标签内嵌(所以它立即执行),而不需要任何forms的逃生时使用的另一种变化:

 <script> var script = document.createElement('script'); script.src = '/path/to/script.js'; document.write(script.outerHTML); </script> 

(注意:与网上的大多数例子相反,我并没有在封闭标签和生成的标签上设置type="text/javascript" :没有浏览器没有默认的,所以它是冗余的,但如果你不同意,也不会伤害)。

Bobince发布的解决scheme对我来说是完美的。 我想为未来的访问者提供另一种方法:

 if (typeof(jQuery) == 'undefined') { (function() { var sct = document.createElement('script'); sct.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js'; sct.type = 'text/javascript'; sct.async = 'true'; var domel = document.getElementsByTagName('script')[0]; domel.parentNode.insertBefore(sct, domel); })(); } 

在这个例子中,我已经包含了一个jQuery的条件加载来演示用例。 希望对某人有用!

Javascriptstring中的</script>由HTMLparsing器解释为结束标记,导致意外的行为( 请参阅JSFiddle上的示例 )。

为了避免这种情况,你可以在注释之间放置你的javascript(这种编码风格是很常见的做法,当浏览器支持Javascript的时候,这种做法是不常见的)。 这将工作( 请参阅JSFiddle中的示例 ):

 <script type="text/javascript"> <!-- if (jQuery === undefined) { document.write('<script type="text/javascript" src="http://z-ecx.images-amazon.comhttp://img.dovov.comG/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></script>'); } // --> </script> 

…但说实话,使用document.write不是我认为最好的做法。 为什么不直接操纵DOM?

 <script type="text/javascript"> <!-- if (jQuery === undefined) { var script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('src', 'http://z-ecx.images-amazon.comhttp://img.dovov.comG/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js'); document.body.appendChild(script); } // --> </script>