第2章 在HTML中使用JavaScript

 

2.1 <script>元素

向HTML页面中插入JavaScript的主要方法,就是使用<script>元素。这个元素由Netscape创造并在Netscape Navigator 2中首先实现。后来,这个元素被加入到正式的HTML规范中。HTML 4.01为<script>定义了下列5个属性。

  • charset : 可选。表示通过 src 属性指定的代码的字符集。由于大多数浏览器会忽略它的值,因此这个属性很少有人用。
  • defer : 可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。
  • language : 已废弃。原来用于表示编写代码使用的脚本语言 (如 JavaScript 、JavaScript 1.2 或 VBScript) 。大多数浏览器会忽略这个属性,因此也没有必要再用了。
  • src : 可选。表示包含要执行代码的外部文件。
  • type : 必需。可以看成是 language 的替代属性;表示编写代码使用的脚本语言的内容类型 (也称为 MIME 类型)。虽然 text/javascript 和 text/ecmascript 都已经不推荐使用,但人们一直以来使用的都还是 text/javascript 。实际上,服务器在传送 JavaScript 文件时使用的 MIME 类型通常是 application/x-javascript ,但是 type 中设置这个值却可能导致脚本被忽略。另外,在非 IE 浏览器中还可以使用以下值: application/javascript 和 application/ecmascript 。考虑到约定俗成和最大限度的浏览器兼容性,目前 type 属性的值依旧还是 text/javascript 。
<script type="text/javascript">
function sayHi() {
alert("Hi!");
}
</script>
包含在 <script> 元素内部的 JavaScript 代码将被从上至下依次解释。 就拿前面这个例子来说,解释器会解释到一个函数的定义,然后将该定义保存在自己的环境当中。在解释器对<script> 元素内部的所有代码求值完毕以前,页面中的其余内容都不会被浏览器加载或显示。
在使用<script>嵌入 JavaScript 代码时,记住不要在代码中的任何地方出现 "</script>" 字符串。例如,浏览器在加载下面所示的代码时就会产生一个错误:
<script type="text/javascript">
function sayScript() {
alert("</script>");
}
</script>
因为按照解析嵌入代码的规则,当浏览器遇到字符串 "</script>" 时,就会认为那是结束的 </script> 标签。而通过把这个字符串分隔为两部分可以解决这个问题,例如:
<script type="text/javascript">
function sayScript() {
alert("</scr“ + ”ipt>");
}
</script>
像这样分成两部分来写就不会造成浏览器的误解,因而也就不会导致错误了。
如果要通过 <script> 元素来包含外部 JavaScript 文件,那么 src 属性就是必需的。这个属性的值是一个指向外部 JavaScript 文件的链接,例如:
<script type="text/javascript" src="example.js"></script>
与解析嵌入式 JavaScript 代码一样,在解析外部 JavaScript 文件 (包括下载该文件) 时,页面的处理也会暂时停止。如果是在 XHTML 文档中,也可以省略前面示例代码中结束的 </script> 标签,例如:
<script type="text/javascript" src="example.js"/>
但是,不能在 HTML 文档使用这种语法。原因是这种语法不符合 HTML 规范,而且也得不到某些浏览器 -- 尤其是 IE -- 的正确解析。
(XHTML : 后缀名为 .xhtml ,包含 <HTML xmlns="http://www.w3.org/1999/xhtml"> ,还有写其他限制)
按照惯例,外部 JavaScript 文件带有 .js 扩展名。但这个扩展名不是必需的,因为浏览器不会检查包含 JavaScript 的文件的扩展名。这样一来,使用 JSP 、PHP 或其他服务器端语言动态生成 JavaScript 代码也就成为了可能。
需要注意的是,带有 src 属性的 <script> 元素不应该在其 <script> 和 </script> 标签之间再包含额外的 JavaScript 代码。
另外,通过 <script> 元素的 src 属性还可以包含来自外部域的 JavaScript 文件。这一点既使 <script> 元素倍显强大,又让它备受争议。在这一点上,<script> 与 <img> 元素非常相似,即它的 src 属性可以是指向当前 HTML 页面所在域之外的某个域中的 URL ,例如:
<script type="text/javascript" src="http://www.somewhere.com/afile.js"></script>
这样,位于外部域中的代码也会被加载和解析,就像这些代码位于加载它们的页面中一样。利用这一点就可以在必要时通过不同的域来提供 JavaScript 文件。
无论如何包含代码,浏览器都会按照 <script> 元素在页面中出现的先后顺序对它们依次进行解析。换句话说,在第一个 <script> 元素包含的代码解析完成后,第二个 <script> 包含的代码才会被解析,然后才是 第三个、第四个......。

2.1.1 标签的位置

按照惯例,所有 <script> 元素都应该放在页面的 <head> 元素中,例如:
这种做法的目的就是把所有外部文件 (包括 CSS 文件和 JavaScript 文件) 的引用都放在相同的地方。可是,在文档的 <head> 元素中包含所有 JavaScript 文件,意味着必须等到全部 JavaScript 代码都被下载、解析和执行完成以后,才能开始呈现页面的内容 (浏览器在遇到 <body> 标签时才开始呈现内容)。对于那些需要很多 JavaScript 代码的页面来说,这无疑会导致浏览器在呈现页面时出现明显的延迟,而延迟期间的浏览器窗口中将是一片空白。为了避免这个问题,现代Web应用程序一般都把全部 JavaScript 引用放在 <body> 元素中,放在页面的内容后面,如下列所示:
这样,在解析包含的 JavaScript 代码之前,页面的内容将完全呈现在浏览器中。而用户也会因为浏览器窗口显示空白页面的时间缩短而感到打开页面的速度加快了。

2.1.2 延迟脚本

HTML 4.01为 <script> 标签定义了 defer 属性。这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解释完毕后再运行。因此,在 <script> 元素中设置 defer 属性 (如下面的例子所示) ,实际上与上一节中介绍的把 <script> 元素放在页面最底部的效果是一样的。
在这个例子中,虽然我们把 <script> 元素放在了文档的 <head> 元素中,但其中包含的脚本将延迟到浏览器遇到 </html> 标签后再执行。
不过,问题是并非所有浏览器都支持 defer 属性。 IE 和 Firefox 3.1 是目前唯一支持 defer 属性的主流浏览器。其他浏览器则会忽略这个属性,不延迟脚本的执行。

2.1.3 在 XHTML 中的用法

可扩展超文本标记语言,即 XHTML (Extensible HyperText Markup Language) ,是将 HTML 作为 XML 的应用而重新定义的一个标准。编写 XHTML 代码的规则要比编写 HTML 严格得多,而且直接影响能否在嵌入 JavaScript 代码时使用 <script/> 标签。以下面的代码块为例,虽然它们在 HTML 中是有效的,但在 XHTML 中则是无效的:
在 HTML 中,有特殊的规则用以确定 <script> 元素中的哪些内容可以被解析,但这些特殊的规则在 XHTML 中不适用。这里比较语句 a < b 中的小于号 (<) 在 XHTML 中将被当作开始一个新标签来解析。但是作为标签来讲,小于号后面不能跟空格,因此就会导致语法错误。
避免在 XHTML 中出现类似语法错误的方法有两个。一个是用相应的 HTML 实体 (&lt;) 替换代码中所有的小于号 (<) ,替换后的代码类似如下所示:
虽然这样可以让代码在 XHTML 中正常运行,但却导致代码不好理解了。为此,我们可以考虑采用另一个方法。
保证让相同代码在 XHTML 中正常运行的第二个方法,就是用一个 CData 片段来包含 JavaScript 代码。 在 XHTML (XML) 中,CData 片段是文档中的一个特殊区域,这个区域中可以包含不需要解析的任意格式的文本内容。因此,在 CData 片段中就可以使用任意字符 -- 小于号当然也没有问题,而且不会导致语法错误。引入 CData 片段后的 JavaScript 代码块如下所示:
在兼容 XHTML 的浏览器中,这个方法可以解决问题。但实际上,还有不少浏览器不兼容 XHTML 因而不支持 CData 片段。怎么办呢?再使用 JavaScript 注释将 CData 标记注释掉就可以了:
这种格式在所有现代浏览器中都可以正常使用。虽然有几分 hack 的味道,但它能通过 XHTML 验证,而且对 XHTML 之前的浏览器也会平稳退化。

2.1.4 不推荐使用的语法

在最早引入 <script> 元素的时候,该元素与传统 HTML 的解析规则是有冲突的。由于要对这个元素应用特殊的解析规则,因此在那些不支持 JavaScript 的浏览器 -- 最典型的是 Mosaic -- 中就会导致问题。具体来说,不支持 JavaScript 的浏览器会把 <script> 元素的内容直接输出到页面中,因而会破坏页面的布局和外观。
Netscape 与 Mosaic 协商并提出了一个解决方案,让不支持 <script> 元素的浏览器能够隐藏嵌入的 JavaScript 代码。这个方案就是把 JavaScript 代码包含在一个 HTML 注释中,像下面这样:
<script><!--
function sayHi(){
alert(" Hi ! ");
}
//--></script>
给脚本加上 HTML 注释后, Mosaic 等浏览器就会忽略 <script> 标签中的内容;而那些支持 JavaScript 的浏览器在遇到这种情况时,则必须进一步确认其中是否包含需要解析的 JavaScript  代码。
虽然这种注释 JavaScript 代码的格式得到了所有浏览器的认可,也能被正确解释,但由于所有浏览器都已经支持 JavaScript ,因此也就没有必要再使用这种格式了。

2.1.5 嵌入代码与外部文件

在 HTML 中嵌入 JavaScript 代码虽然没有问题,但一般认为最好的做法还是尽可能使用外部文件来包含 JavaScript 代码。不过,并不存在必须使用外部文件的硬性规定,但支持使用外部文件的人多会强调如下优点。
可维护性  -- 遍及不同 HTML 页面的 JavaScript 会造成维护问题。但把所有 JavaScript 文件都放在一个文件夹中,维护起来就轻松多了。而且开发人员因此也能够在不触及 HTML 标记的情况下,集中精力编辑 JavaScript 代码。
可缓存  -- 浏览器能够根据具体的设置缓存链接的所有外部 JavaScript 文件。也就是说,如果有两个页面都使用同一个文件,那么这个文件只需下载一次。因此,最终结果就是能够加快页面加载的速度。
可适应未来  -- 通过外部文件来包含 JavaScript 无须使用前面提到 XHTML 或注释 hack 。HTML 和 XHTML 包含外部文件的语法是相同的。

2.2 文档模式

IE 5.5 引入了文档模式的概念,而这个概念是通过使用文档类型 (doctype) 切换实现的。 最初的两种文档模式是: 混杂模式 (quirks mode) 和标准模式 (standards mode) 。混杂模式会让IE的行为与 (包含非标准特性的) IE5 相同,而标准模式则让 IE 的行为更接近标准行为。虽然这两种模式主要影响 CSS 内容的呈现,但在某些情况下也会影响到 JavaScript 的解释执行。
在IE引入文档模式的概念后,其他浏览器也纷纷效仿。 在此之后,IE又提出一种所谓的准标准模式 (almost standards mode) 。这种模式下的浏览器特性有很多都是符合标准的,但也不尽然。 不标准的地方主要体现在处理图片间隙的时候 (在表格中使用图片时问题最明显) 。
如果在文档开始处没有发现文档类型声明,则所有浏览器都会默认开启混杂模式。但采用混杂模式不是什么值得推荐的做法,因为不同浏览器在这种模式下的行为差异非常大,如果不使用某些 hack 技术,跨浏览器的行为根本就没有一致性可言。
对于标准模式,可以通过使用下面任何一种文档类型来开启:
而对于准标准模式,则可以通过使用过渡型 (transitional) 或框架型 (frameset) 文档类型来触发,如下所示:
准标准模式与标准模式非常接近,它们的差异几乎可以忽略不计。因此,当有人提到 “标准模式” 时,有可能是指这两种模式中的任何一种。而且,检测文档模式时也不会发现什么不同。
IE8又引入了一种新的文档模式,叫做超级标准模式。超级文档模式可以让 IE 以其所有版本中最符合标准的方式来解释网页内容。总的来看,混杂模式让IE像 IE5 ,标准模式使用IE7的呈现引擎,而超级标准模式则是 IE8的默认文档模式 -- 不过,在IE8中使用下面这个特殊的 <meta> 值可以关闭其默认文档模式:
其中,content 属性中 IE 的值用于指定使用哪个版本的呈现引擎呈现页面。设计这个值的目的就是为了向后兼容那些专门为老版本的 IE 设计的站点和页面。
与标准模式类似,超级标准模式与标准模式一般也不会有什么差别。因此,本书在提到标准模式时,指的是除混杂模式之外的其他所有模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值