打印

HS9001: IE Opera 中 src 属性为空的 SCRIPT 元素内的脚本不会被忽略,且内联脚本可以通过修改其所在 SCRIPT 元素的 src 属性引入新的外部脚本文件

作者:陆远

标准参考

HTML 4.01 规范中提到,脚本可以定义在页面的 SCRIPT 元素内,或者外部文件中。若 SCRIPT 元素没有设置 src 属性,则用户端必须将元素的内容当做脚本去解释。若 src 属性指定了一个 URI,则用户端必须忽略元素的内容切通过 URI 获取脚本。

关于 SCRIPT 元素的详细信息,请参考 HTML 4.01 规范 18.2.1 The SCRIPT element 中的内容。

问题描述

在 IE 和 Opera 中,若 SCRIPT 元素设定了 src 属性但值为空,则其内脚本并不会被忽略,而是可以正常被解释执行。同时,一段内联脚本可以通过修改其所在 SCRIPT 元素的 src 属性引入新的外部脚本文件。

造成的影响

这个问题将导致部分脚本在 Firefox Chrome Safari 中无法被执行。

受影响的浏览器

IE6 IE7 IE8 Opera  

问题分析

SCRIPT 元素本身就具有二义性。在其未设置 src 属性的时候,其内的内容作为内联脚本被执行。若设定了一个正确的外部脚本文件 URI,则其内容应被忽略,转而仅执行外部脚本文件中的代码。

各浏览器对 src 属性没有设定以及正确的引入了外部脚本文件时的 SCRIPT 元素的处理均相同,但是在设定了 src 属性,但属性值为空的情况,各浏览器中产生了差异。

分析以下代码:script_with_empty_src.html

<!DOCTYPE html>
<html>
<head>
</head>
<body style="font:16px Arial;">
<script src="">
  document.write('&lt;script src=""&gt; is interpreted.<br />');
</script>
<script>
  document.write('&lt;script&gt; is interpreted.<br />');
</script>
</body>
</html>

上述代码中包含两个 SCRIPT 元素,其内脚本分别通过 document.write 方法向页面文档流中写入了两段内容。第一个 SCRIPT 元素设定了 src 属性为空字符串,第二段没有设定 src 属性。

这段代码在各浏览器中运行效果如下:

IE6 IE7 IE8 Opera Firefox Chrome Safari
<script src=""> is interpreted.
<script> is interpreted.
<script> is interpreted.

可见,在 IE Opera 中,设定了值为空1的 src 属性内的脚本依然可以被执行,虽然设定了 src 属性,但浏览器并没有将它们忽略。
而在 Firefox Chrome Safari 中,浏览器忽略了设定了 src 属性的 SCRIPT 元素内的脚本内容,这一点符合 W3C 规范。

注 1:对于 <script src> 情况相同。


下面再看另一种情况,在一个未设定 src 属性的 SCRIPT 元素内的脚本中动态修改这个 SCRIPT 的 src 属性试图引入新的外部脚本文件的情况下,各浏览器的处理同样产生了差异。

分析以下代码:inline_script_modifies_its_src_of_tag.html

<!DOCTYPE html>
<html>
<head>
</head>
<body style="font:16px Arial;">
<script>
  document.write('&lt;script&gt; is interpreted.<br />');
  document.getElementsByTagName("script")[0].src = "a.js";
</script>
</body>
</html>

a.js

document.write('&lt;script src="a.js"&gt; is interpreted.<br />');

页面中有一个 SCRIPT 元素,其内脚本向页面文档流中写入了一段内容,然后对其所在的 SCRIPT 元素的 src 属性进行了修改,试图引入一个新的外部脚本文件“a.js”,“a.js”内的脚本为向页面文档流内写入另一段内容。

这段代码在各浏览器中运行效果如下:

IE6 IE7 IE8 Opera Firefox Chrome Safari
<script> is interpreted.
<script src="a.js"> is interpreted.
<script> is interpreted.

可见,在 IE Opera 中,一个未设定 src 属性的 SCRIPT 元素内的脚本中动态修改这个 SCRIPT 的 src 属性成功的引入了一个新的外部脚本文件,并且脚本文件中的脚本可以被解释执行。
而在 Firefox Chrome Safari 中,语句 document.getElementsByTagName("script")[0].src = "a.js"; 虽然已在在文档树中将 SCRIPT 元素的 src 属性修改,但浏览器并没有真正引入这个外部脚本文件,更没有执行其内的脚本。

虽然 HTML 规范中并没有明确说明这种情况下用户端应如何处理,但当动态的为 SCRIPT 元素设定 src 属性引入外部脚本文件后,原 SCRIPT 元素内的脚本内容该如何处理就出现了模糊不清的情况。所以在编写代码时就应当避免在这种歧义的发生。

解决方案

不在设定了 src 属性的 SCRIPT 元素内编写脚本。
不通过脚本修改当前脚本所在 SCRIPT 元素的 src 属性。
以避免歧义的发生。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.8
Chrome 6.0.472.25 dev
Safari 5.0.1
Opera 10.60
测试页面: script_with_empty_src.html
inline_script_modifies_its_src_of_tag.html
本文更新时间: 2010-08-08

关键字

SCRIPT JavaScript src URI URL 脚本 text content