在 HTML 中嵌入 JavaScript 代碼雖然沒有問題,但一般認為最好的做法還是盡可能使用外部文件來包含 JavaScript 代碼。不過,并不存在必須使用外部文件的硬性規定,但支持使用外部文件的人多會強調如下優點。
可維護性:遍及不同 HTML 頁面的 JavaScript 會造成維護問題。但把所有 JavaScript 文件都放在一個文件夾中,維護起來就輕松多了。而且開發人員因此也能夠在不觸及 HTML 標記的情況下,集中精力編輯 JavaScript 代碼。
可緩存:瀏覽器能夠根據具體的設置緩存鏈接的所有外部 JavaScript 文件。也就是說,如果有兩個頁面都使用同一個文件,那么這個文件只需下載一次。因此,最終結果就是能夠加快頁面加載的速度。
適應未來:通過外部文件來包含 JavaScript 無須使用前面提到 XHTML 或注釋 hack。 HTML 和XHTML 包含外部文件的語法是相同的。
2.3 文檔模式
IE5.5 引入了文檔模式的概念,而這個概念是通過使用文檔類型(doctype)切換實現的。最初的兩種文檔模式是: 混雜模式(quirks mode)①和標準模式(standards mode)。混雜模式會讓 IE 的行為與(包含非標準特性的)IE5 相同,而標準模式則讓 IE 的行為更接近標準行為。雖然這兩種模式主要影響 CSS內容的呈現,但在某些情況下也會影響到 JavaScript 的解釋執行。本書將在必要時再討論這些因文檔模式而影響 JavaScript 執行的情況。
在 IE 引入文檔模式的概念后,其他瀏覽器也紛紛效仿。在此之后, IE 又提出一種所謂的準標準模式(almost standards mode)。這種模式下的瀏覽器特性有很多都是符合標準的,但也不盡然。不標準的地方主要體現在處理圖片間隙的時候(在表格中使用圖片時問題最明顯)。
如果在文檔開始處沒有發現文檔類型聲明,則所有瀏覽器都會默認開啟混雜模式。但采用混雜模式不是什么值得推薦的做法,因為不同瀏覽器在這種模式下的行為差異非常大,如果不使用某些 hack 技術,跨瀏覽器的行為根本就沒有一致性可言。
對于標準模式,可以通過使用下面任何一種文檔類型來開啟:
<!-- HTML 4.01 嚴格型 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!-- XHTML 1.0 嚴格型 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- HTML 5 -->
<!DOCTYPE html>
而對于準標準模式,則可以通過使用過渡型(transitional)或框架集型(frameset)文檔類型來觸發,如下所示:
<!-- HTML 4.01 過渡型 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- HTML 4.01 框架集型 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<!-- XHTML 1.0 過渡型 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- XHTML 1.0 框架集型 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
準標準模式與標準模式非常接近,它們的差異幾乎可以忽略不計。因此,當有人提到“標準模式”時,有可能是指這兩種模式中的任何一種。而且,檢測文檔模式(本書后面將會討論)時也不會發現什么不同。本書后面提到標準模式時,指的是除混雜模式之外的其他模式。
① 這里 quirks mode 的譯法源自 Firefox 3.5.5 中文版。
2.4 <noscript>元素
早期瀏覽器都面臨一個特殊的問題,即當瀏覽器不支持 JavaScript 時如何讓頁面平穩地退化。對這個問題的最終解決方案就是創造一個<noscript>元素,用以在不支持 JavaScript 的瀏覽器中顯示替代的內容。這個元素可以包含能夠出現在文檔<body>中的任何 HTML 元素——<script>元素除外。包含在<noscript>元素中的內容只有在下列情況下才會顯示出來:
瀏覽器不支持腳本;
瀏覽器支持腳本,但腳本被禁用。
符合上述任何一個條件,瀏覽器都會顯示<noscript>中的內容。而在除此之外的其他情況下,瀏覽器不會呈現<noscript>中的內容。請看下面這個簡單的例子:
<html>
<head>
<title>
Example HTML Page
</title>
<script type="text/javascript" defer="defer" src="example1.js"></script>
<script type="text/javascript" defer="defer" src="example2.js">
</script>
</head>
<body>
<noscript>
<p>本頁面需要瀏覽器支持(啟用) JavaScript。
</noscript>
</body>
</html>
這個頁面會在腳本無效的情況下向用戶顯示一條消息。而在啟用了腳本的瀏覽器中,用戶永遠也不會看到它——盡管它是頁面的一部分。
2.5 小結
把 JavaScript 插入到 HTML 頁面中要使用<script>元素。使用這個元素可以把 JavaScript 嵌入到HTML 頁面中,讓腳本與標記混合在一起;也可以包含外部的 JavaScript 文件。而我們需要注意的地方有:
在包含外部 JavaScript 文件時,必須將 src 屬性設置為指向相應文件的 URL。而這個文件既可以是與包含它的頁面位于同一個服務器上的文件,也可以是其他任何域中的文件。
所有<script>元素都會按照它們在頁面中出現的先后順序依次被解析。在不使用 defer 和async 屬性的情況下,只有在解析完前面<script>元素中的代碼之后,才會開始解析后面<script>元素中的代碼。
由于瀏覽器會先解析完不使用 defer 屬性的<script>元素中的代碼,然后再解析后面的內容,所以一般應該把<script>元素放在頁面最后,即主要內容后面, </body>標簽前面。
使用 defer 屬性可以讓腳本在文檔完全呈現之后再執行。延遲腳本總是按照指定它們的順序執行。
使用 async 屬性可以表示當前腳本不必等待其他腳本,也不必阻塞文檔呈現。不能保證異步腳本按照它們在頁面中出現的順序執行。
另外,使用<noscript>元素可以指定在不支持腳本的瀏覽器中顯示的替代內容。但在啟用了腳本的情況下,瀏覽器不會顯示<noscript>元素中的任何內容。