当浏览器遇到<script>标签时,页面的加载、介些都会停下来,运行此javascript代码,而后再继续加载。这种事情一样会发生在那些以"src"属性调用的外部脚本,浏览器首先下载外部文件的代码,这要占用一些时间,而后在运行这些代码,这又要占用一些时间。此过程当中,页面的解析与用户的交互都是阻塞的。javascript
无论是内联脚本仍是外部脚本,都应该尽可能放在<body>
标签结束以前(除非某些脚本须要在页面加载完以前调用),这样能够保证在运行脚本以前,页面已经基本加载完成。java
延时脚本
能够给script
标签添加一个属性 - defer ,这个属性代表:元素中的脚本不打算修改DOM,所以代码能够稍后执行。带有这个属性的任何script
元素中的脚本都不会在DOM加载完以前执行,若是是外部脚本,这些脚本首先并行下载,而不会执行,因此不会阻塞页面的加载。实例代码以下:<script src="./script/file1.js" defer>
浏览器
动态脚本元素
DOM容许你经过脚原本建立script
元素,像下面这样:app
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "./script/file1.js"; document.getElementsByTagName("head")[0].appendChild(script);
此文件元素添加到页面后当即开始下载。此技术的重点在于:不管在何处启动下载,脚本的下载和运行都不会阻塞页面的处理过程。
为方便使用,我整合了一个动态加载脚本的方法:url
function loadJS(url, callback) { var script = document.creatElement("script"); script.type = "text/script"; if(script.readyState) { script.onreadystatechange = function() { if(script.readyState == "loaded" || script.readyState == "complete") { script.onreadystatechange = null; callback; } }; }else { script.onload = function() { callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
XMLHttpRequest 脚本注入
另外一个以非阻塞的方式得到脚本的方法是使用XHR对象将脚本注入到页面中。此技术先建立一个XHR对象,而后下载脚本文件,接着用一个动态的script
元素将javascript代码注入页面:code
var xhr = new XMLHttpRequest(); xhr.open("get", "./scripts/file1.js", true); xhr.onreadystatechange = function(){ if(xhr.readyState == 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 400) { var script = document.createElement("script"); script.type = "text/javascript"; script.text = xhr.responseText; document.body.appendChild(script); } } }; xhr.send(null); };
此方法的限制是,你必须下载同一个域下的文件,不能从CDN下载。对象