javaScript教程(三)

瀏覽器模型

瀏覽器環境概述

JavaScript 是瀏覽器的內置腳本語言。也就是說,瀏覽器內置了 JavaScript 引擎,並且提供各種接口,讓 JavaScript 腳本可以控制瀏覽器的各種功能。一旦網頁內嵌了 JavaScript 腳本,瀏覽器加載網頁,就會去執行腳本,從而達到操作瀏覽器的目的,實現網頁的各種動態效果。

這裏開始介紹瀏覽器提供的各種 JavaScript 接口。首先,介紹 JavaScript 代碼嵌入網頁的方法

代碼嵌入網頁的方法

網頁中嵌入 JavaScript 代碼,主要有四種方法:

script 元素嵌入代碼

<script>
  var x = 1 + 5;
  console.log(x);
</script>

1.text/javascript:這是默認值,也是歷史上一貫設定的值。如果你省略type屬性,默認就是這個值。對於老式瀏覽器,設爲這個值比較好

2.application/javascript:對於較新的瀏覽器,建議設爲這個值

由於

<script id="mydata" type="x-custom-data">
  console.log('Hello World');
</script>

瀏覽器不會執行也不會顯示內容,因爲不認識它的type屬性;但是,這個

document.getElementById('mydata').text // console.log('Hello World');

script 元素加載外部腳本

<script src="https://www.example.com/script.js"></script>

如果腳本文件使用了非英語字符,還應該註明字符的編碼

<script charset="utf-8" src="https://www.example.com/script.js"></script>

所加載的腳本必須是純的 JavaScript 代碼,不能有HTML代碼和

<script charset="utf-8" src="example.js">
  console.log('Hello World!');
</script>

爲了防止攻擊者篡改外部腳本,script標籤允許設置一個integrity屬性,寫入該外部腳本的 Hash 簽名,用來驗證腳本的一致性

<script src="/assets/application.js" integrity="sha256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs="></script>

上面代碼中,script標籤有一個integrity屬性,指定了外部腳本/assets/application.js的 SHA256 簽名。一旦有人改了這個腳本,導致 SHA256 簽名不匹配,瀏覽器就會拒絕加載

事件屬性

網頁元素的事件屬性(比如onclick和onmouseover),可以寫入 JavaScript 代碼。當指定事件發生時,就會調用這些代碼

<button id="myBtn" onclick="console.log(this.id)">點擊</button> //如果有多個語句,使用分號分隔即可

URL 協議

URL 支持javascript:協議,即在 URL 的位置寫入代碼,使用這個 URL 的時候就會執行 JavaScript 代碼

<a href="javascript:console.log('Hello')">點擊</a>

瀏覽器的地址欄也可以執行javascript:協議。將javascript:console.log('Hello')放入地址欄,按回車鍵也會執行這段代碼;如果 JavaScript 代碼返回一個字符串,瀏覽器就會新建一個文檔,展示這個字符串的內容,原有文檔的內容都會消失

<a href="javascript: new Date().toLocaleTimeString();">點擊</a>

上面代碼中,用戶點擊鏈接以後,會打開一個新文檔,裏面有當前時間;如果返回的不是字符串,那麼瀏覽器不會新建文檔,也不會跳轉

<a href="javascript: console.log(new Date().toLocaleTimeString())">點擊</a>

javascript:協議的常見用途是書籤腳本 Bookmarklet。由於瀏覽器的書籤保存的是一個網址,所以javascript:網址也可以保存在裏面,用戶選擇這個書籤的時候,就會在當前頁面執行這個腳本。爲了防止書籤替換掉當前文檔,可以在腳本前加上void,或者在腳本最後加上void 0

<a href="javascript: void new Date().toLocaleTimeString();">點擊</a>
<a href="javascript: new Date().toLocaleTimeString();void 0;">點擊</a>

script 元素

工作原理

瀏覽器加載 JavaScript 腳本,主要通過

1.瀏覽器一邊下載 HTML 網頁,一邊開始解析;也就是說,不等到下載完,就開始解析

2.解析過程中,瀏覽器發現

3.如果

4.JavaScript 引擎執行完畢,控制權交還渲染引擎,恢復往下解析 HTML 網頁

加載外部腳本時,瀏覽器會暫停頁面渲染,等待腳本下載並執行完成後再繼續渲染;原因是 JavaScript 代碼可以修改 DOM,所以必須把控制權讓給它,否則會導致複雜的線程競賽的問題。如果外部腳本加載時間很長(一直無法完成下載),那麼瀏覽器就會一直等待腳本下載完成,造成網頁長時間失去響應,瀏覽器就會呈現“假死”狀態,這被稱爲“阻塞效應”。爲了避免這種情況,較好的做法是將

<head>
  <script>
    console.log(document.body.innerHTML);
  </script>
</head>
<body></body>

上面代碼執行時會報錯,因爲此時document.body元素還未生成

一種解決方法是設定DOMContentLoaded事件的回調函數

<head>
  <script>
    document.addEventListener(
      'DOMContentLoaded',
      function (event) {
        console.log(document.body.innerHTML);
      }
    );
  </script>
</head>

DOMContentLoaded事件只有在 DOM 結構生成之後纔會觸發

另一種解決方法是使用

<script src="jquery.min.js" onload="console.log(document.body.innerHTML)"></script>

但是,如果將腳本放在頁面底部,就可以完全按照正常的方式寫,上面兩種方式都不需要。如果有多個script標籤,比如下面這樣:

<script src="a.js"></script>
<script src="b.js"></script>

瀏覽器會同時並行下載a.js和b.js,但是,執行時會保證先執行a.js,然後再執行b.js,即使後者先下載完成,也是如此。也就是說,腳本的執行順序由它們在頁面中的出現順序決定,這是爲了保證腳本之間的依賴關係不受到破壞。當然,加載這兩個腳本都會產生“阻塞效應”,必須等到它們都加載完成,瀏覽器纔會繼續頁面渲染。解析和執行 CSS,也會產生阻塞。Firefox 瀏覽器會等到腳本前面的所有樣式表,都下載並解析完,再執行腳本;Webkit則是一旦發現腳本引用了樣式,就會暫停執行腳本,等到樣式表下載並解析完,再恢復執行。

此外,對於來自同一個域名的資源,比如腳本文件、樣式表文件、圖片文件等,瀏覽器一般有限制,同時最多下載6~20個資源,即最多同時打開的 TCP 連接有限制,這是爲了防止對服務器造成太大壓力。如果是來自不同域名的資源,就沒有這個限制。所以,通常把靜態文件放在不同的域名之下,以加快下載速度

defer 屬性

爲了解決腳本文件下載阻塞網頁渲染的問題,一個方法是對

<script src="a.js" defer></script>
<script src="b.js" defer></script>

上面代碼中,只有等到 DOM 加載完成後,纔會執行a.js和b.js

defer屬性的運行流程如下:

1.瀏覽器開始解析 HTML 網頁

2.解析過程中,發現帶有defer屬性的

3.瀏覽器繼續往下解析 HTML 網頁,同時並行下載

4.瀏覽器完成解析 HTML 網頁,此時再回過頭執行已經下載完成的腳本

有了defer屬性,瀏覽器下載腳本文件的時候,不會阻塞頁面渲染。下載的腳本文件在DOMContentLoaded事件觸發前執行(即剛剛讀取完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章