script、script async、script defer 之间的不同

向html页面中插入javascript代码的主要方法就是通过script标签。其中包括两种形式,第一种直接在script标签之间插入js代码,第二种即是通过src属性引入外部js文件。由于解释器在解析执行js代码期间会阻塞页面其余部分的渲染,对于存在大量js代码的页面来说会导致浏览器出现长时间的空白和延迟,为了避免这个问题,建议把全部的js引用放在< /body>标签之前。

资源加载和页面事件
理想的页面加载方式

解析HTML结构。
加载并解析外部脚本。
DOM树构建完成,执行脚本。//DOMInteractive –> DOMContentLoaded 加载图片、样式表文件等外部文件。
页面加载完毕。//window.onload 涉及到的事件 window.onload: 当页面全部加载完成(包括所有资源)
document.onload: 当整个html文档加载的时候就触发了,也就是在body元素加载之前就开始执行了
DOMContentLoaded: 当页面的DOM树解析好并且需要等待JS执行完才触发
DOMContentLoaded事件不直接等待CSS文件、图片的加载完成 onreadytstatechange: 当对象状态变更时触发这个事件,一旦document的readyState属性发生变化就会触发

defer和async
没有defer和async浏览器会立即加载并执行指定的脚本,不等待后续载入的文档元素,读到就加载并执行。
当加载脚本时会阻塞页面的渲染。

有async
加载和渲染后续文档元素的过程将和脚本的加载与执行并行进行,体现出来就是异步。async JS一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。
如果脚本前后有依赖性,用async,就很有可能出错。

有defer
加载后续文档元素的过程将和脚本的加载并行进行,
但是脚本的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成。
defer JS在DOMInteractive后执行,一旦执行完defer JS,就会触发DOMContentLoaded。
也就是说defer脚本总是在DOMInteractive事件与DOMContentLoaded事件之间的时间执行。
defer JS在html页面解析完毕之后再去执行,也就是类似于把这个脚本放在了页面底部。

DOM的加载与解析
DOMLoading
浏览器开始解析dom树的时间点

DOMInteractive
表示浏览器已经解析好dom树了。

DOMContentLoaded
同步的JS已经执行完毕了。

load的实现
作用:监控整个文档(包括资源)是否加载完毕,所有资源加载完毕后触发
原生js写法:

window.onload = function(){

}

jquery写法:

$(document).load(function(){

});

document.ready的实现
作用:监控dom是否加载完毕,dom加载完毕时及资源加载之前触发
原生js写法:

document.ready = function(callback) {
    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', function() {
            document.removeEventListener('DOMContentLoaded', arguments.callee, false);
            callback();
        }, false);
    }else if (document.attachEvent) {// 兼容ie
        document.attachEvent('onreadytstatechange', function() {
            if (document.readyState == "complete") {
                document.detachEvent("onreadystatechange", arguments.callee);
                callback();
            }
        });
    }
}

以下为jquery的写法:

$(function(){

});

$(document).ready(function(){

});

//jquery中默认为document对象
$().ready(function(){

});

script标签存在两个属性,defer和async,因此script标签的使用分为三种情况:

1.<script src="example.js"></script>

没有defer或async属性,浏览器会立即加载并执行相应的脚本。也就是说在渲染script标签之后的文档之前,不等待后续加载的文档元素,读到就开始加载和执行,此举会阻塞后续文档的加载;

2.<script async src="example.js"></script>

有了async属性,表示后续文档的加载和渲染与js脚本的加载和执行是并行进行的,即异步执行;

3.<script defer src="example.js"></script>

有了defer属性,加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本的执行需要等到文档所有元素解析完成之后,DOMContentLoaded事件触发执行之前。

1.defer和async在网络加载过程是一致的,都是异步执行的;

2.两者的区别在于脚本加载完成之后何时执行,可以看出defer更符合大多数场景对应用脚本加载和执行的要求;

3.如果存在多个有defer属性的脚本,那么它们是按照加载顺序执行脚本的;而对于async,它的加载和执行是紧紧挨着的,无论声明顺序如何,只要加载完成就立刻执行,它对于应用脚本用处不大,因为它完全不考虑依赖。

小结:

defer 和 async 的共同点是都是可以并行加载JS文件,不会阻塞页面的加载,不同点是 defer的加载完成之后,JS会等待整个页面全部加载完成了再执行,而async是加载完成之后,会马上执行JS,所以假如对JS的执行有严格顺序的话,那么建议用 defer加载。

参考链接: https://blog.csdn.net/weixin_42561383/article/details/86564715
https://blog.csdn.net/u011700203/article/details/47656857

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值