Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一区在线视频,一区视频在线播放,中文字幕资源在线

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML中的JavaScript

          習目標:了解JavaScript是如何與HTML結合來創建動態網頁,網頁中嵌入JavaScript的不同方式,JavaScript的內容類型及其與<script>的關系

          <script>元素

          <script>是由Netscape創造出來,后來加到HTML規范中的。

          <script>有8個屬性:

          1、async:表示立即開始下載腳本,但不能阻止其他頁面動作,比如下載資源或者等待其他腳本加載。只對外部腳本文件有效。

          2、charset:使用src屬性指定代碼字符集。這個屬性很少用,因為大多數瀏覽器不在乎它的值。

          3、crossorigin;配置資源請求的CORS(跨源資源共享)設置。默認情況下不使用CORS。crossorigin = “anonymous”配置文件請求不用設置憑據標志。crossorigin = ”use-credentials“設置憑據標志,意味著出站請求會包含憑據。

          4、defer:表示腳本可以延遲到文檔全部解析和顯示后再執行。新版本中只能用于外部腳本。

          5、integrity:允許比對接收到的資源和指定的加密簽名以驗證子資源完整性(SRI,Subresource integrity),如果驗證簽名不匹配則腳本不會執行。這個屬性可以用于確保內容分發網絡(CDN,Content Delivery Network)不會提供惡意內容。

          6、language:此屬性已被廢止。

          7、src:表示包含外部要執行的代碼的外部文件。

          8、type:代替language,表示代碼塊中腳本語言的內容類型(也稱為MIME類型),按照慣例這個值始終都是”text/JavaScript“,盡管”text/JavaScript“和”text/ecmascript“都已經廢棄。JavaScript文件的MIME類型通常是”application/x-javascript“,不過給type屬性這個值的話可能會導致腳本被忽略。在非IE的瀏覽器中有效的值還有”application/JavaScript“和”application/ecmascript"。如果這個值是module,則代碼會被當成是ES6模塊,而且只有這時候代碼中才能出現import和export關鍵字。

          使用<script>的方式有內聯和外嵌兩種,只要把code寫入<script>code</script>中就好,code中要是包含字符串“<script>”,只要加上轉義字符“\”即可。

          如果要外嵌JavaScript代碼只要使用src屬性來鏈接外部文件即可如:

          <script src=“example.js”></script>

          XHTML 文檔中,可以忽略結束標簽寫成<script src=“example.js”/>即可,但是這在HTML中不能使用。

          標簽位置

          過去把JavaScript和CSS一起寫在head中,但是這意味著必須下載所有code并解析和解釋完成后才開始渲染頁面,對于JavaScript很多的頁面會導致頁面渲染速度過慢,為解決這個問題,JavaScript一般寫在body元素的頁面內容的最后邊,如下

          <html>

          <head></head>

          <body>

          message

          <script>code<\script>

          <\body>

          </html>

          推遲使用腳本

          在外聯JavaScript時可以使用defer屬性來推遲腳本的運行??梢詫懗桑?/p>

          <html>

          <head>

          <script defer src = "example.js">code<\script>

          </head>

          <body>

          message

          <\body>

          </html>

          異步執行腳本

          async屬性從腳本處理方式上與defer類似,但是不同的是標記async的腳本并不能保證腳本按照他們的出現順序執行,比如:

          <html>

          <head>

          <script sync src = "example1.js">code<\script>

          <script sync src = "example2.js">code<\script>

          </head>

          <body>

          message

          <\body>

          </html>

          不能保證example1比example2先執行。

          動態加載腳本

          除了<script>以外還可以用其他方式加載腳本。因為JavaScript可以使用DOM API,所以通過向DOM中動態地加入script元素同樣可以加載指定腳本。只要創建一個script元素并將其添加到DOM即可。

          let script = document.createElement('script');

          script.src = 'gibberish.js';

          document.head.appendChild(script);

          當然,在把 HTMLElement 元素添加到 DOM 且執行到這段代碼之前不會發送請求。默認情況下,以這種方式創建的<script>元素是以異步方式加載的,相當于添加了 async 屬性。不過這樣做可能會有問題,因為所有瀏覽器都支持 createElement()方法,但不是所有瀏覽器都支持 async 屬性。因此,如果要統一動態腳本的加載行為,可以明確將其設置為同步加載:

          let script = document.createElement('script');

          script.src = 'gibberish.js';

          script.async = false;

          document.head.appendChild(script);

          以這種方式獲取的資源對瀏覽器預加載器是不可見的。這會嚴重影響它們在資源獲取隊列中的優先級。根據應用程序的工作方式以及怎么使用,這種方式可能會嚴重影響性能。要想讓預加載器知道這些動態請求文件的存在,可以在文檔頭部顯式聲明它們:

          <link rel="preload" href="gibberish.js">

          XHTML中的變化

          可擴展超文本標記語言(XHTML,Extensible HyperText Markup Language)是將 HTML 作為 XML的應用重新包裝的結果。與 HTML 不同,在 XHTML 中使用 JavaScript 必須指定 type 屬性且值為text/javascript,HTML 中則可以沒有這個屬性。XHTML 雖然已經退出歷史舞臺,但實踐中偶爾可能也會遇到遺留代碼,為此本節稍作介紹。在 XHTML 中編寫代碼的規則比 HTML 中嚴格,這會影響使用<script>元素嵌入 JavaScript 代碼。下面的代碼塊雖然在 HTML 中有效,但在 XHML 中是無效的。

          <script type="text/javascript">

          function compare(a, b) {

          if (a < b) {

          console.log("A is less than B");

          } else if (a > b) {

          console.log("A is greater than B");

          } else {

          console.log("A is equal to B");

          }

          }

          </script>

          在 HTML 中,解析<script>元素會應用特殊規則。XHTML 中則沒有這些規則。這意味著 a < b語句中的小于號(<)會被解釋成一個標簽的開始,并且由于作為標簽開始的小于號后面不能有空格,這會導致語法錯誤。避免 XHTML 中這種語法錯誤的方法有兩種。第一種是把所有小于號(<)都替換成對應的 HTML實體形式(<)。結果代碼就是這樣的:

          <script type="text/javascript">

          function compare(a, b) {

          if (a < b) {

          console.log("A is less than B");

          } else if (a > b) {

          console.log("A is greater than B");

          } else {

          console.log("A is equal to B");

          }

          }

          </script>

          這樣代碼就可以在 XHTML 頁面中運行了。不過,缺點是會影響閱讀。好在還有另一種方法。第二種方法是把所有代碼都包含到一個 CDATA 塊中。在 XHTML(及 XML)中,CDATA 塊表示文檔中可以包含任意文本的區塊,其內容不作為標簽來解析,因此可以在其中包含任意字符,包括小于號,并且不會引發語法錯誤。使用 CDATA 的格式如下:

          <script type="text/javascript"><![CDATA[

          function compare(a, b) {

          if (a < b) {

          console.log("A is less than B");

          } else if (a > b) {

          console.log("A is greater than B");

          } else {

          console.log("A is equal to B");

          }

          }

          ]]></script>

          在兼容 XHTML 的瀏覽器中,這樣能解決問題。但在不支持 CDATA 塊的非 XHTML 兼容瀏覽器中則不行。為此,CDATA 標記必須使用 JavaScript 注釋來抵消:

          <script type="text/javascript">

          //<![CDATA[

          function compare(a, b) {

          if (a < b) {

          console.log("A is less than B");

          } else if (a > b) {

          console.log("A is greater than B");

          } else {

          console.log("A is equal to B");

          }

          }

          //]]>

          </script>

          這種格式適用于所有現代瀏覽器。雖然有點黑科技的味道,但它可以通過 XHTML 驗證,而且對XHTML 之前的瀏覽器也能優雅地降級。

          廢棄的語法

          自 1995 年 Netscape 2 發布以來,所有瀏覽器都將 JavaScript 作為默認的編程語言。type 屬性使用一個 MIME 類型字符串來標識<script>的內容,但 MIME 類型并沒有跨瀏覽器標準化。即使瀏覽器默認使用 JavaScript,在某些情況下某個無效或無法識別的 MIME 類型也可能導致瀏覽器跳過(不執行)相關代碼。因此,除非你使用 XHTML 或<script>標簽要求或包含非 JavaScript 代碼,最佳做法是不指定 type 屬性。在最初采用 script 元素時,它標志著開始走向與傳統 HTML 解析不同的流程。對這個元素需要應用特殊的解析規則,而這在不支持 JavaScript 的瀏覽器(特別是 Mosaic)中會導致問題。不支持的瀏覽器會把<script>元素的內容輸出到頁面上,從而破壞頁面的外觀。Netscape 聯合 Mosaic 拿出了一個解決方案,對不支持 JavaScript 的瀏覽器隱藏嵌入的 JavaScript 代碼。最終方案是把腳本代碼包含在一個 HTML 注釋中,像這樣:

          <script><!--

          function sayHi(){

          console.log("Hi!");

          }

          //--></script>

          使用這種格式,Mosaic 等瀏覽器就可以忽略<script>標簽中的內容,而支持 JavaScript 的瀏覽器則必須識別這種模式,將其中的內容作為 JavaScript 來解析。雖然這種格式仍然可以被所有瀏覽器識別和解析,但已經不再必要,而且不應該再使用了。在XHTML 模式下,這種格式也會導致腳本被忽略,因為代碼處于有效的 XML 注釋當中。

          行內代碼與外部文件

          雖然可以直接在 HTML 文件中嵌入 JavaScript 代碼,但通常認為最佳實踐是盡可能將 JavaScript 代碼放在外部文件中。不過這個最佳實踐并不是明確的強制性規則。推薦使用外部文件的理由如下。

          ? 可維護性。JavaScript 代碼如果分散到很多 HTML 頁面,會導致維護困難。而用一個目錄保存所有 JavaScript 文件,則更容易維護,這樣開發者就可以獨立于使用它們的 HTML 頁面來編輯代碼。

          ? 緩存。瀏覽器會根據特定的設置緩存所有外部鏈接的 JavaScript 文件,這意味著如果兩個頁面都用到同一個文件,則該文件只需下載一次。這最終意味著頁面加載更快。

          ? 適應未來。通過把 JavaScript 放到外部文件中,就不必考慮用 XHTML 或前面提到的注釋黑科技。包含外部 JavaScript 文件的語法在 HTML 和 XHTML 中是一樣的。在配置瀏覽器請求外部文件時,要重點考慮的一點是它們會占用多少帶寬。在 SPDY/HTTP2 中,預請求的消耗已顯著降低,以輕量、獨立 JavaScript 組件形式向客戶端送達腳本更具優勢。比如,第一個頁面包含如下腳本:

          <script src="mainA.js"></script>

          <script src="component1.js"></script>

          <script src="component2.js"></script>

          <script src="component3.js"></script>

          ...

          后續頁面可能包含如下腳本:

          <script src="mainB.js"></script>

          <script src="component3.js"></script>

          <script src="component4.js"></script>

          <script src="component5.js"></script>

          ...

          在初次請求時,如果瀏覽器支持 SPDY/HTTP2,就可以從同一個地方取得一批文件,并將它們逐個放到瀏覽器緩存中。從瀏覽器角度看,通過 SPDY/HTTP2 獲取所有這些獨立的資源與獲取一個大JavaScript 文件的延遲差不多。在第二個頁面請求時,由于你已經把應用程序切割成了輕量可緩存的文件,第二個頁面也依賴的某些組件此時已經存在于瀏覽器緩存中了。當然,這里假設瀏覽器支持 SPDY/HTTP2,只有比較新的瀏覽器才滿足。如果你還想支持那些比較老的瀏覽器,可能還是用一個大文件更合適。

          文檔模式

          IE5.5 發明了文檔模式的概念,即可以使用 doctype 切換文檔模式。最初的文檔模式有兩種:混雜模式(quirks mode)和標準模式(standards mode)。前者讓 IE 像 IE5 一樣(支持一些非標準的特性),后者讓 IE 具有兼容標準的行為。雖然這兩種模式的主要區別只體現在通過 CSS 渲染的內容方面,但對JavaScript 也有一些關聯影響,或稱為副作用。本書會經常提到這些副作用。

          IE 初次支持文檔模式切換以后,其他瀏覽器也跟著實現了。隨著瀏覽器的普遍實現,又出現了第三種文檔模式:準標準模式(almost standards mode)。這種模式下的瀏覽器支持很多標準的特性,但是沒有標準規定得那么嚴格。主要區別在于如何對待圖片元素周圍的空白(在表格中使用圖片時最明顯)。

          混雜模式在所有瀏覽器中都以省略文檔開頭的 doctype 聲明作為開關。這種約定并不合理,因為混雜模式在不同瀏覽器中的差異非常大,不使用黑科技基本上就沒有瀏覽器一致性可言。標準模式通過下列幾種文檔類型聲明開啟:

          <!-- HTML 4.01 Strict -->

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

          "http://www.w3.org/TR/html4/strict.dtd">

          <!-- XHTML 1.0 Strict -->

          <!DOCTYPE html PUBLIC

          "-//W3C//DTD XHTML 1.0 Strict//EN"

          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

          <!-- HTML5 -->

          <!DOCTYPE html>

          準標準模式通過過渡性文檔類型(Transitional)和框架集文檔類型(Frameset)來觸發:

          <!-- HTML 4.01 Transitional -->

          <!DOCTYPE HTML PUBLIC

          "-//W3C//DTD HTML 4.01 Transitional//EN"

          "http://www.w3.org/TR/html4/loose.dtd">

          <!-- HTML 4.01 Frameset -->

          <!DOCTYPE HTML PUBLIC

          "-//W3C//DTD HTML 4.01 Frameset//EN"

          "http://www.w3.org/TR/html4/frameset.dtd">

          <!-- XHTML 1.0 Transitional -->

          <!DOCTYPE html PUBLIC

          "-//W3C//DTD XHTML 1.0 Transitional//EN"

          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

          <!-- XHTML 1.0 Frameset -->

          <!DOCTYPE html PUBLIC

          "-//W3C//DTD XHTML 1.0 Frameset//EN"

          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

          準標準模式與標準模式非常接近,很少需要區分。人們在說到“標準模式”時,可能指其中任何一個。而對文檔模式的檢測(本書后面會討論)也不會區分它們。本書后面所說的標準模式,指的就是除混雜模式以外的模式。

          <noscript>元素

          針對早期瀏覽器不支持 JavaScript 的問題,需要一個頁面優雅降級的處理方案。最終,<noscript>元素出現,被用于給不支持 JavaScript 的瀏覽器提供替代內容。雖然如今的瀏覽器已經 100%支持JavaScript,但對于禁用 JavaScript 的瀏覽器來說,這個元素仍然有它的用處。<noscript>元素可以包含任何可以出現在<body>中的 HTML 元素,<script>除外。在下列兩種情況下,瀏覽器將顯示包含在<noscript>中的內容:

          ? 瀏覽器不支持腳本;

          ? 瀏覽器對腳本的支持被關閉。任何一個條件被滿足,包含在<noscript>中的內容就會被渲染。否則,瀏覽器不會渲染<noscript>中的內容。

          下面是一個例子:

          <!DOCTYPE html>

          <html>

          <head>

          <title>Example HTML Page</title>

          <script defer="defer" src="example1.js"></script>

          <script defer="defer" src="example2.js"></script>

          </head>

          <body>

          <noscript>

          <p>This page requires a JavaScript-enabled browser.</p>

          </noscript>

          </body>

          </html>

          這個例子是在腳本不可用時讓瀏覽器顯示一段話。如果瀏覽器支持腳本,則用戶永遠不會看到它。

          小結

          JavaScript 是通過<script>元素插入到 HTML 頁面中的。這個元素可用于把 JavaScript 代碼嵌入到HTML 頁面中,跟其他標記混合在一起,也可用于引入保存在外部文件中的 JavaScript。本章的重點可以總結如下。

          ? 要包含外部 JavaScript 文件,必須將 src 屬性設置為要包含文件的 URL。文件可以跟網頁在同一臺服務器上,也可以位于完全不同的域。

          ? 所有<script>元素會依照它們在網頁中出現的次序被解釋。在不使用 defer 和 async 屬性的情況下,包含在<script>元素中的代碼必須嚴格按次序解釋。

          ? 對不推遲執行的腳本,瀏覽器必須解釋完位于<script>元素中的代碼,然后才能繼續渲染頁面的剩余部分。為此,通常應該把<script>元素放到頁面末尾,介于主內容之后及</body>標簽之前。

          ? 可以使用 defer 屬性把腳本推遲到文檔渲染完畢后再執行。推遲的腳本原則上按照它們被列出的次序執行。

          ? 可以使用 async 屬性表示腳本不需要等待其他腳本,同時也不阻塞文檔渲染,即異步加載。異步腳本不能保證按照它們在頁面中出現的次序執行。

          ? 通過使用<noscript>元素,可以指定在瀏覽器不支持腳本時顯示的內容。如果瀏覽器支持并啟用腳本,則<noscript>元素中的任何內容都不會被渲染。

          來了~歡迎轉發、收藏,記得點個贊唄。^_^

          無論當前 JavaScript 代碼是內嵌還是在外鏈文件中,頁面的下載和渲染都必須停下來等待腳本執行完成。JavaScript 執行過程耗時越久,瀏覽器等待響應用戶輸入的時間就越長。瀏覽器在下載和執行腳本時出現阻塞的原因在于,腳本可能會改變頁面或 JavaScript 的命名空間,它們對后面頁面內容造成影響。一個典型的例子就是在頁面中使用document.write()。例如清單 1。

          清單 1 JavaScript 代碼內嵌示例

          當瀏覽器遇到<script>標簽時,當前 HTML 頁面無從獲知 JavaScript 是否會向<p> 標簽添加內容,或引入其他元素,或甚至移除該標簽。因此,這時瀏覽器會停止處理頁面,先執行 JavaScript代碼,然后再繼續解析和渲染頁面。同樣的情況也發生在使用 src 屬性加載 JavaScript的過程中,瀏覽器必須先花時間下載外鏈文件中的代碼,然后解析并執行它。在這個過程中,頁面渲染和用戶交互完全被阻塞了。

          1.腳本位置

          HTML 4 規范指出 <script> 標簽可以放在 HTML 文檔的<head>或<body>中,并允許出現多次。Web 開發人員一般習慣在 <head> 中加載外鏈的 JavaScript,接著用 <link> 標簽用來加載外鏈的 CSS 文件或者其他頁面信息。例如清單 2。

          清單 2 低效率腳本位置示例

          然而這種常規的做法卻隱藏著嚴重的性能問題。在清單 2 的示例中,當瀏覽器解析到 <script> 標簽(第 4 行)時,瀏覽器會停止解析其后的內容,而優先下載腳本文件,并執行其中的代碼,這意味著,其后的 styles.css 樣式文件和<body>標簽都無法被加載,由于<body>標簽無法被加載,那么頁面自然就無法渲染了。因此在該 JavaScript 代碼完全執行完之前,頁面都是一片空白。圖 1 描述了頁面加載過程中腳本和樣式文件的下載過程。

          圖 1 JavaScript 文件的加載和執行阻塞其他文件的下載

          我們可以發現一個有趣的現象:第一個 JavaScript 文件開始下載,與此同時阻塞了頁面其他文件的下載。此外,從 script1.js 下載完成到 script2.js 開始下載前存在一個延時,這段時間正好是 script1.js 文件的執行過程。每個文件必須等到前一個文件下載并執行完成才會開始下載。在這些文件逐個下載過程中,用戶看到的是一片空白的頁面。

          從 IE 8、Firefox 3.5、Safari 4 和 Chrome 2 開始都允許并行下載 JavaScript 文件。這是個好消息,因為<script>標簽在下載外部資源時不會阻塞其他<script>標簽。遺憾的是,JavaScript 下載過程仍然會阻塞其他資源的下載,比如樣式文件和圖片。盡管腳本的下載過程不會互相影響,但頁面仍然必須等待所有 JavaScript 代碼下載并執行完成才能繼續。因此,盡管最新的瀏覽器通過允許并行下載提高了性能,但問題尚未完全解決,腳本阻塞仍然是一個問題。

          由于腳本會阻塞頁面其他資源的下載,因此推薦將所有<script>標簽盡可能放到<body>標簽的底部,以盡量減少對整個頁面下載的影響。例如清單 3

          清單 3 推薦的代碼放置位置示例

          這段代碼展示了在 HTML 文檔中放置<script>標簽的推薦位置。盡管腳本下載會阻塞另一個腳本,但是頁面的大部分內容都已經下載完成并顯示給了用戶,因此頁面下載不會顯得太慢。

          這是優化 JavaScript 的首要規則:將腳本放在底部。

          2.組織腳本

          由于每個<script>標簽初始下載時都會阻塞頁面渲染,所以減少頁面包含的<script>標簽數量有助于改善這一情況。這不僅針對外鏈腳本,內嵌腳本的數量同樣也要限制。瀏覽器在解析 HTML 頁面的過程中每遇到一個<script>標簽,都會因執行腳本而導致一定的延時,因此最小化延遲時間將會明顯改善頁面的總體性能。

          這個問題在處理外鏈 JavaScript 文件時略有不同??紤]到 HTTP 請求會帶來額外的性能開銷,因此下載單個 100Kb 的文件將比下載 5 個 20Kb 的文件更快。也就是說,減少頁面中外鏈腳本的數量將會改善性能。

          通常一個大型網站或應用需要依賴數個 JavaScript 文件。您可以把多個文件合并成一個,這樣只需要引用一個<script>標簽,就可以減少性能消耗。文件合并的工作可通過離線的打包工具或者一些實時的在線服務來實現。

          需要特別提醒的是,把一段內嵌腳本放在引用外鏈樣式表的<link>之后會導致頁面阻塞去等待樣式表的下載。這樣做是為了確保內嵌腳本在執行時能獲得最精確的樣式信息。因此,建議不要把內嵌腳本緊跟在<link>標簽后面。

          3.無阻塞的腳本

          減少 JavaScript 文件大小并限制 HTTP 請求數在功能豐富的 Web 應用或大型網站上并不總是可行。Web 應用的功能越豐富,所需要的 JavaScript 代碼就越多,盡管下載單個較大的 JavaScript 文件只產生一次 HTTP 請求,卻會鎖死瀏覽器的一大段時間。為避免這種情況,需要通過一些特定的技術向頁面中逐步加載 JavaScript 文件,這樣做在某種程度上來說不會阻塞瀏覽器。

          無阻塞腳本的秘訣在于,在頁面加載完成后才加載 JavaScript 代碼。這就意味著在 window 對象的 onload事件觸發后再下載腳本。有多種方式可以實現這一效果。

          3.1延遲加載腳本

          HTML 4 為<script>標簽定義了一個擴展屬性:defer。Defer 屬性指明本元素所含的腳本不會修改 DOM,因此代碼能安全地延遲執行。defer 屬性只被 IE 4 和 Firefox 3.5 更高版本的瀏覽器所支持,所以它不是一個理想的跨瀏覽器解決方案。在其他瀏覽器中,defer 屬性會被直接忽略,因此<script>標簽會以默認的方式處理,也就是說會造成阻塞。然而,如果您的目標瀏覽器支持的話,這仍然是個有用的解決方案。清單 4 是一個例子

          清單 4 defer 屬性使用方法示例

          <script type="text/javascript" src="script1.js" defer></script>

          帶有 defer 屬性的<script>標簽可以放置在文檔的任何位置。對應的 JavaScript 文件將在頁面解析到<script>標簽時開始下載,但不會執行,直到 DOM 加載完成,即onload事件觸發前才會被執行。當一個帶有 defer 屬性的 JavaScript 文件下載時,它不會阻塞瀏覽器的其他進程,因此這類文件可以與其他資源文件一起并行下載。

          任何帶有 defer 屬性的<script>元素在 DOM 完成加載之前都不會被執行,無論內嵌或者是外鏈腳本都是如此。清單 5 的例子展示了defer屬性如何影響腳本行為:

          清單 5 defer 屬性對腳本行為的影響

          這段代碼在頁面處理過程中彈出三次對話框。不支持 defer 屬性的瀏覽器的彈出順序是:"defer"、"script"、"load"。而在支持 defer 屬性的瀏覽器上,彈出的順序則是:"script"、"defer"、"load"。請注意,帶有 defer 屬性的<script>元素不是跟在第二個后面執行,而是在 onload 事件被觸發前被調用。

          如果您的目標瀏覽器只包括 Internet Explorer 和 Firefox 3.5,那么 defer 腳本確實有用。如果您需要支持跨領域的多種瀏覽器,那么還有更一致的實現方式。

          HTML 5 為<script>標簽定義了一個新的擴展屬性:async。它的作用和 defer 一樣,能夠異步地加載和執行腳本,不因為加載腳本而阻塞頁面的加載。但是有一點需要注意,在有 async 的情況下,JavaScript 腳本一旦下載好了就會執行,所以很有可能不是按照原本的順序來執行的。如果 JavaScript 腳本前后有依賴性,使用 async 就很有可能出現錯誤。

          3.2動態腳本元素

          文檔對象模型(DOM)允許您使用 JavaScript 動態創建 HTML 的幾乎全部文檔內容。<script>元素與頁面其他元素一樣,可以非常容易地通過標準 DOM 函數創建:

          清單 6 通過標準 DOM 函數創建<script>元素

          新的<script>元素加載 script1.js 源文件。此文件當元素添加到頁面之后立刻開始下載。此技術的重點在于:無論在何處啟動下載,文件的下載和運行都不會阻塞其他頁面處理過程。您甚至可以將這些代碼放在<head>部分而不會對其余部分的頁面代碼造成影響(除了用于下載文件的 HTTP 連接)。

          當文件使用動態腳本節點下載時,返回的代碼通常立即執行(除了 Firefox 和 Opera,他們將等待此前的所有動態腳本節點執行完畢)。當腳本是"自運行"類型時,這一機制運行正常,但是如果腳本只包含供頁面其他腳本調用調用的接口,則會帶來問題。這種情況下,您需要跟蹤腳本下載完成并是否準備妥善。可以使用動態 <script> 節點發出事件得到相關信息。

          Firefox、Opera, Chorme 和 Safari 3+會在<script>節點接收完成之后發出一個 onload 事件。您可以監聽這一事件,以得到腳本準備好的通知:

          清單 7 通過監聽 onload 事件加載 JavaScript 腳本

          Internet Explorer 支持另一種實現方式,它發出一個 readystatechange 事件。<script>元素有一個 readyState 屬性,它的值隨著下載外部文件的過程而改變。readyState 有五種取值:

          &middot; "uninitialized":默認狀態

          &middot; "loading":下載開始

          &middot; "loaded":下載完成

          &middot; "interactive":下載完成但尚不可用

          &middot; "complete":所有數據已經準備好

          微軟文檔上說,在<script>元素的生命周期中,readyState 的這些取值不一定全部出現,但并沒有指出哪些取值總會被用到。實踐中,我們最感興趣的是"loaded"和"complete"狀態。Internet Explorer 對這兩個 readyState 值所表示的最終狀態并不一致,有時<script>元素會得到"loader"卻從不出現"complete",但另外一些情況下出現"complete"而用不到"loaded"。最安全的辦法就是在 readystatechange 事件中檢查這兩種狀態,并且當其中一種狀態出現時,刪除 readystatechange 事件句柄(保證事件不會被處理兩次):

          清單 8 通過檢查 readyState 狀態加載 JavaScript 腳本

          大多數情況下,您希望調用一個函數就可以實現 JavaScript 文件的動態加載。下面的函數封裝了標準實現和 IE 實現所需的功能:

          清單 9 通過函數進行封裝

          此函數接收兩個參數:JavaScript 文件的 URL,和一個當 JavaScript 接收完成時觸發的回調函數。屬性檢查用于決定監視哪種事件。最后一步,設置 src 屬性,并將<script>元素添加至頁面。此 loadScript() 函數使用方法如下:

          清單 10 loadScript()函數使用方法

          您可以在頁面中動態加載很多 JavaScript 文件,但要注意,瀏覽器不保證文件加載的順序。所有主流瀏覽器之中,只有 Firefox 和 Opera 保證腳本按照您指定的順序執行。其他瀏覽器將按照服務器返回它們的次序下載并運行不同的代碼文件。您可以將下載操作串聯在一起以保證他們的次序,如下:

          清單 11 通過 loadScript()函數加載多個 JavaScript 腳本

          此代碼等待 script1.js 可用之后才開始加載 script2.js,等 script2.js 可用之后才開始加載 script3.js。雖然此方法可行,但如果要下載和執行的文件很多,還是有些麻煩。如果多個文件的次序十分重要,更好的辦法是將這些文件按照正確的次序連接成一個文件。獨立文件可以一次性下載所有代碼(由于這是異步進行的,使用一個大文件并沒有什么損失)。

          動態腳本加載是非阻塞 JavaScript 下載中最常用的模式,因為它可以跨瀏覽器,而且簡單易用。

          3.3使用 XMLHttpRequest(XHR)對象

          此技術首先創建一個 XHR 對象,然后下載 JavaScript 文件,接著用一個動態 <script> 元素將 JavaScript 代碼注入頁面。清單 12 是一個簡單的例子:

          清單 12 通過 XHR 對象加載 JavaScript 腳本

          此代碼向服務器發送一個獲取 script1.js 文件的 GET 請求。onreadystatechange 事件處理函數檢查 readyState 是不是 4,然后檢查 HTTP 狀態碼是不是有效(2XX 表示有效的回應,304 表示一個緩存響應)。如果收到了一個有效的響應,那么就創建一個新的<script>元素,將它的文本屬性設置為從服務器接收到的 responseText 字符串。這樣做實際上會創建一個帶有內聯代碼的<script>元素。一旦新<script>元素被添加到文檔,代碼將被執行,并準備使用。

          這種方法的主要優點是,您可以下載不立即執行的 JavaScript 代碼。由于代碼返回在<script>標簽之外(換句話說不受<script>標簽約束),它下載后不會自動執行,這使得您可以推遲執行,直到一切都準備好了。另一個優點是,同樣的代碼在所有現代瀏覽器中都不會引發異常。

          此方法最主要的限制是:JavaScript 文件必須與頁面放置在同一個域內,不能從 CDN 下載(CDN 指"內容投遞網絡(Content Delivery Network)",所以大型網頁通常不采用 XHR 腳本注入技術。

          4.總結

          一般而言,減少 JavaScript 對性能的影響有以下幾種方法:

          &middot; A.將所有的<script>標簽放到頁面底部,也就是</body>閉合標簽之前,這能確保在腳本執行前頁面已經完成了渲染。

          &middot; B.盡可能地合并腳本。頁面中的<script>標簽越少,加載也就越快,響應也越迅速。無論是外鏈腳本還是內嵌腳本都是如此。

          &middot; C.采用無阻塞下載 JavaScript 腳本的方法:

          &middot; a-使用<script>標簽的 defer 屬性(僅適用于 IE 和 Firefox 3.5 以上版本);

          &middot; b-使用動態創建的<script>元素來下載并執行代碼;

          &middot; c-使用 XHR 對象下載 JavaScript 代碼并注入頁面中。

          通過以上策略,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 網站和應用的實際性能。


          看完了,別忘了收藏、轉發、點個贊,更別忘了要關注本號!^_^

          • JavaScript輸出文本

          • 用JavaScript改變HTML元素

          • 一個外部JavaScript



          • 實例解析

          JavaScript 語句、注釋和代碼塊

          • JavaScript 語句

          • JavaScript 代碼塊

          • JavaScript 單行注釋

          • JavaScript 多行注釋

          • 使用單行注釋來防止執行

          • 使用多行注釋來防止執行

          • 實例解析

          JavaScript 變量

          • 聲明一個變量,為它賦值,然后顯示出來

          • 實例解析

          JavaScript 條件語句 If ... Else

          • If 語句

          • If...else 語句

          • 隨機鏈接

          • Switch 語句

          • 實例解析

          JavaScript 消息框

          • Alert(警告)框

          • 帶有換行的警告框

          • 確認框

          • 提示框

          • 實例解析

          JavaScript 函數

          • 函數

          • 帶有參數的函數

          • 帶有參數的函數 2

          • 返回值的函數

          • 帶有參數并返回值的函數

          • 實例解析

          JavaScript 循環

          • For 循環

          • 循環輸出 HTML 標題

          • While 循環

          • Do while 循環

          • break 語句

          • continue 語句

          • 使用 For...In 聲明來遍歷數組內的元素

          • 實例解析

          JavaScript 事件

          • onclick事件

          • onmouseover 事件

          • 實例解析

          JavaScript 錯誤處理

          • try...catch 語句

          • 帶有確認框的 try...catch 語句

          • onerror 事件

          • 實例解析

          高級 JavaScript 實例

          • 創建一個歡迎 cookie

          • 簡單的計時

          • 另一個簡單的計時

          • 在一個無窮循環中的計時事件

          • 帶有停止按鈕的無窮循環中的計時事件

          • 使用計時事件制作的鐘表

          • 創建對象的實例

          • 創建用于對象的模板



          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!


          主站蜘蛛池模板: 中文字幕色AV一区二区三区| 天堂va在线高清一区| 久久免费区一区二区三波多野| 中文字幕乱码人妻一区二区三区| 国产精品av一区二区三区不卡蜜| 久久se精品动漫一区二区三区| 日韩一区在线视频| 日韩中文字幕一区| 麻豆aⅴ精品无码一区二区| 亚洲第一区精品观看| 久久一区二区三区精华液使用方法| 久久一区二区明星换脸| 风间由美性色一区二区三区| 国产精品福利区一区二区三区四区| 精品视频一区二区| 无码欧精品亚洲日韩一区夜夜嗨 | 日韩伦理一区二区| 波多野结衣一区二区| 成人中文字幕一区二区三区| 精品一区精品二区制服| 蜜桃无码一区二区三区| 国产精品夜色一区二区三区| 精品国产一区二区三区不卡 | 国产精品香蕉一区二区三区| 人妻久久久一区二区三区| 精品无码一区在线观看| 日韩精品无码中文字幕一区二区| 国产精品美女一区二区视频| 亚洲国产成人一区二区三区| 国偷自产一区二区免费视频| 久久免费区一区二区三波多野| 久久er99热精品一区二区 | 午夜视频在线观看一区二区| 在线观看一区二区三区视频| 精品一区二区三区AV天堂| 中文字幕一区精品| 日产亚洲一区二区三区| 中文字幕一区二区三区5566| 无码日韩人妻av一区免费| 国产一区二区在线| 亚洲Aⅴ无码一区二区二三区软件|