Javascript的同步加载和执行

现在的前端技术中,javascript(以下简称 js)异步加载的方案已经很多。在研究异步加载前,我们对同步加载了解的够多么?

同步加载大概意思为:浏览器解析文档的过程中,遇到加载 js 文件的代码,暂停文档解析,执行加载的代码,等待文件下载,等待文件中的代码执行完成,然后继续文档解析。

所以异步加载就是:浏览器解析文档过程中,遇到加载 js 文件的代码,暂停文档解析,执行加载代码,然后继续文档解析。不等待文件的下载。

同步加载的几种情况:

1、包含代码的 <script></script> 标签。虽然没有网络请求,但也可以当做是加载了文档内部的一段代码。标签内的代码按顺序执行,如果出现多个标签对,按标签对的出现顺序执行。

2、设置 src 属性的 <script></script> 标签。按标签的出现顺序执行。老的浏览器中,加载也是按顺序的:一个文件下载完成后,才开始下载下一个文件。较新的浏览器中(IE8+ 、FireFox3.5+ 、Chrome4+ 、Safari4+),为了减小请求时间以优化体验,下载可以是并行的,但是执行顺序还是按照标签出现的顺序。

3、在 <script></script> 标签中的代码,或者通过 src 引用的文件中,使用 document.write() 来写入的 js 代码。代码中也有上面 1 和 2 两种情况,执行顺序也是按照出现的先后。在 IE 中有个例外,在 <script></script> 标签中,假设有这种 document.write(‘<script src=””><\/script>’) 加载文件的代码,则文件会放到 </script> 标签闭合处才执行。

同步加载的执行顺序:

因为核心 js 语言并不包含任何线程机制,并且浏览器端 js 也没增加任何线程机制,所以浏览器端 js 是单线程的(或者像单线程一样工作)。因此 js 代码只能按顺序执行,就算浏览器为了体验可以并行下载多个 js 文件,但就算个别文件下载的特别快,也得按顺序被执行。

同步加载的应用:

1、我们平时的开发中用的基本上都是同步加载。比如先加载一个 jQuery 库文件,接下来就可以使用 $ 符号了。原理上,是因为 js 代码的运行环境是在一个全局对象里,代码声明全局变量和函数,实际是在修改全局对象的属性,这些修改会被保持着,所以下一段代码可以使用上一段代码声明的全局变量和函数。

2、常用于跨域请求数据的 JSONP。我们在本站声明一个回调函数,然后向外站请求一个 js 文件,文件中的代码是用外站的数据对本站函数进行调用,就实现了使用外站数据的目的。虽然函数是本站声明的,数据是外站的,外站调用本站函数,但是把它理解为同步加载和执行就简单了。

3、前端优化中的 “脚本尽量放在页面底部” 这条规则,也很好解释。因为是同步加载和执行,js 的加载和执行都会阻塞页面的解析,如果时间长了,体验很不好,所以将脚本尽量放在底部,影响最小。

几个容易混淆的问题:

1、将 document.write(‘<script src=””><\/script>’) 这类代码,移到 window.onload 事件中,算异步加载么?

还是同步加载。这样改其实是改变了这段加载代码的执行时机,推迟到文件加载完成时才执行,但并没有改变加载的方式。

2、同步加载第 3 中情况中,如果嵌套了很多层,执行顺序是怎样的?比如,在被加载的 js 文件中,又用 document.write() 来加载了一个 js 文件。

还是按出现顺序来执行。根据单线程的模型,只能逐个解析和执行。

最后站在浏览器的角度总结下:因为浏览器的 js 是单线程的,而且 js 都运行在 window 这个全局对象中,所以必须逐个解析、加载和执行 <script></script> 标签中包含的代码或文件;为了保证这种顺序,需要同步加载 js 文件。

打赏此文

如果您觉得本站的内容对您有所帮助,您可以扫描下面的二维码小额支付请我喝杯茶,感谢!打赏记录
支付宝
微信
承诺:凡打赏捐助的朋友,留言备注自己的邮箱,在打赏捐助时间点的6个月内,本站会每周邮件推送原创专业技术博文,供大家学习和参考!

留下评论

All fields marked (*) are required