1. 程式人生 > >script標籤中的async和defer屬性

script標籤中的async和defer屬性

眾所周知,html中的script標籤都是同步按順序來執行的,並且在載入和執行的時候會中斷DOM解析器的解析過程,下面列舉一個簡單的例子來觀察這一過程:

loadjs.html程式碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Load Script</title>
</head>
<body>
<h1>Load javascript testing</h1>
<script type="text/javascript" src="./js/a.js" ></script>
<script type="text/javascript" src="./js/b.js" ></script>
<h2>defer & async</h2>
</body>
</html>
這裡為了有利於觀察,在載入a.js這個檔案時後臺服務會增加一個延遲5s的響應時間

頁面顯示效果一:

我們可以看到頁面先顯示"Load javascript testing", 等待5秒之後才顯示"defer & async",很顯然,載入和執行js指令碼確實中斷了DOM的解析和渲染。

html5中script標籤支援async和defer屬性,這兩個屬性是做什麼的呢,檢視w3c文件你可以知道如果script標籤有async或者defer屬性,那麼載入和執行指令碼將不會block DOM的解析和渲染,眼見為實:

修改loadjs.html程式碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Load Script</title>
</head>
<body>
<h1>Load javascript testing</h1>
<script type="text/javascript" src="./js/a.js" async></script>
<script type="text/javascript" src="./js/b.js" async></script>
<h2>defer & async</h2>
</body>
</html>

頁面顯示效果二:


頁面是渲染不會受js指令碼的影響而同時顯示"Load javascript testing"和"defer & async"。

async和defer有什麼區別呢,兩者最重要的區別是什麼時候去執行指令碼:

Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script. The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) that async scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’s DOMContentLoaded event.

loadjs.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Load Script</title>
<link rel="stylesheet" href="./style/jquery-ui.css">
</head>
<body>
<h1>Load javascript testing</h1>
<script type="text/javascript" src="./js/a.js" async></script>
<script type="text/javascript" src="./js/b.js" async></script>
<h2>defer & async</h2>
</body>
</html>

a.js內容:

var globalA = 'globalA';
var globalFunction = function(){
    return 'I am global function created in a.js';
};
b.js內容:
var globalB = 'globalB';
console.log(globalFunction());

結果:在執行
console.log(globalFunction());
時丟擲異常:<span style="font-family: Arial, Helvetica, sans-serif;">Uncaught ReferenceError: globalFunction is not defined,如果就async改成defer,將不會丟擲此異常</span>