由于浏览器中的JavaScript代码在执行过程中会阻塞浏览器的其他进程,比如用户界面绘制;页面中遇到外链的<script>标签时,页面必须停下来等待代码下载并执行,然后继续处理其他部分。
在开发中如果把javascript脚本直接放在</head>标签前,会导致页面渲染不及时,导致用户体验极差。
面对此类问题,以下方法能够有效减少JavaScript加载对性能的影响:
①将所有的<script>标签放到</body>闭合标签之前,以确保在脚本执行前页面先行完成渲染;
②合并脚本。页面中的<script>标签越少,加载也就越快,响应也更迅速。无论外链文件还是内嵌脚本都是如此。
③用多种无阻塞下载JavaScript代码并注入页面中。
(1)使用<script>标签的 defer 属性;
(2)使用动态创建的<script>元素来下载并执行代码;
function loadScript(Url, callback){ var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; if(script.readyState){ script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ //IE script.onreadystatechange = null; callback(); } }; } else { //others browers script.onload = function(){ callback(); }; } script.src = Url; head.appendChild(script); }
(3)使用XHR对象下载 JavaScript 代码并注入页面中。
function loadXMLScript(url,callback){ var xhr = new XMLHttpRequest(); xhr.open("get",url,true); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ var script = document.createElement("script"); script.type = "text/javascript"; script.text = xhr.responseText; document.body.appendChild(script); callback(); } } } xhr.send(null); } }
注:这段代码发送一个GET请求获取JS文件。事件处理函数onReadyStateChange 检查readyState 是否为4,同时校验HTTP状态码是否有效(2XX表示有效响应,304意味着是从缓存读取)。如果收到了有效响应,
就会创建一个<script>元素,设置该元素的 text 属性为从服务器接收到的 resposeText.这样实际上相当于创建一个带有内联脚本的<script>标签。一旦新创建的<script>元素被添加到页面,代码就会立刻执行
然后准备就绪。
局限性:JavaScript文件必须与所请求的页面处于相同的域,js代码会嵌入HTML页面,不够美观。