资讯专栏INFORMATION COLUMN

Script标签和脚本执行顺序 - 文档加载 - 面向浏览器编程

cangck_X / 1846人阅读

摘要:相关脚本会立即下载并执行。从上面两个例子,可以充分了解到标签的柱塞式执行。表示该标签并不柱塞,也不同步执行。属性带有属性的脚本,同样会推迟脚本的执行,并且不会阻止文档解析。同时,带有的脚本彼此之间,能保证其执行顺序。

  

原文: http://pij.robinqu.me/Browser_Scripting/Document_Loading/ScriptTag.html

  

源代码: https://github.com/RobinQu/Programing-In-Javascript/blob/master/chapters/Browser_Scripting/Document_Loading/ScriptTag.md

本文需要补充更多例子

本文存在批注,但该网站的Markdown编辑器不支持,所以无法正常展示,请到原文参考。

Script标签和脚本执行顺序

这里详细聊聊和script标签相关的脚本执行顺序。

Script标签的默认行为

几个首要特性:

script标签(不带deferasync属性)的会阻止文档渲染。相关脚本会立即下载并执行。

document.currentScript可以获得当前正在运行的脚本(Chrome 29+, FF4+)

脚本顺序再默认情况下和script标签出现的顺序一致

假设如下简单代码1,最终会产生三个alert依次为“A”、“B”、“C”。





我们再考虑有网络请求的情况2





三个文件都需要先下载再运行,且第二个文件的尺寸远大于另外两个文件。但结果依然是弹出三个alert,内容分别是"A"、"B"、"C"。

从上面两个例子,可以充分了解到script标签的柱塞式执行。

async属性

async属性是HTML5的新特性3,这意味着其兼容性并不乐观(IE10+)。

async表示该script标签并不柱塞,也不同步执行。浏览器只需要在脚本下载完毕后再执行即可——不必柱塞页面渲染等待该脚本的下载和执行。

如下代码4,会得到三个alert,但是alert的内容分别是"A","C","B"。





可以看到,第二个script标签在加入async并没有阻止后续文档解析和脚本执行。

考究这个属性产生的原有,其实有大量的脚本加载器在做这样的事情:

var script = document.createElement("script");
script.src = "file.js";
document.body.appendChild(script);

不难想象,通过脚本异步插入的script标签达到的效果和带async属性的script标签是一样的。换句话说,由脚本插入的script标签默认是async的。

另外,对內联脚本设置async属性是没有意义的,也不产生其他效果。其包含的脚本总是立即执行的。

defer属性

带有defer属性的脚本,同样会推迟脚本的执行,并且不会阻止文档解析。就如同这个脚本,放置到了文档的末尾(之前)。

如下代码5的宏观现象和加了async属性的例子是一样的,都会得到"A"、"C"、"B"的三个alert。但是其原理是不一样的。





defer属性是会确保脚本在文档解析完毕后执行的——即使这个脚本在文档解析过程中就已经下载完毕变成可执行的状态,浏览器也会推迟这个脚本的执行,直到文档解析完毕6,并在DOMContentLoaded之前7

同时,带有defer的脚本彼此之间,能保证其执行顺序。

注意,defer属性并不是每个浏览器支持,即便支持的浏览器,也会因为版本不一样导致具体行为不一致。另外,大家可以通过将script标签放置到文档末尾这种简单的做法达到defer属性一样的效果。

defer属性早在IE4就被支持,但是这个defer属性和现代浏览器的行为是有区别的。只有IE10以上,才开始按照标准执行defer属性。

async与defer的影响

参考W3C的官方文档8,defer和async两个属性是可以互相影响的:

  

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.

简单的归纳:

仅有async属性,脚本会异步执行

仅有defer属性,脚本会在文档解析完毕后执行

两个属性都没有,脚本会被同步下载并执行,期间会柱塞文档解析

规范里没有提到两种属性都有时的效果,但这是文档中被允许的。这样的具体效果会在后面讨论。

document.write的影响

docuemnt.write允许向打开的文档流中写入文档内容;内嵌到HTML里面的docuemnt.write可以就地添加文档内容。考虑到docuemnt.write写入script标签的情况9:



");

观察到执行顺序和普通的script标签没有区别。即使你插入的标签带有async或defer,其行为也是没有区别的。

让人纠结的是反过来10使用。由于第二个脚本是通过document.write写入的。被延迟的脚本在执行时,document已经关闭,document.write是没有任何效果的。所以,不管使用defer还是async,第二个脚本始终没有运行。

浏览器兼容性 defer属性

点击查看

async属性

点击查看

测试用例

TODO

http://t.cn/RvApb3D ↩

http://t.cn/RvApGke ↩

http://www.w3.org/html/wg/drafts/html/master/scripting-1.html#attr-script-async ↩

http://t.cn/RvApq3G ↩

http://t.cn/RvAp5xj ↩

http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/ ↩

https://www.webkit.org/blog/1395/running-scripts-in-webkit/ ↩

http://www.w3.org/html/wg/drafts/html/master/scripting-1.html#attr-script-defer ↩

http://t.cn/RvApt7Q ↩

http://t.cn/RvAptOo ↩

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78129.html

相关文章

  • 脚本执行方式 - 文档加载 - 面向览器编程

    摘要:脚本执行方式执行入口标签函数构造函数和函数标签内的事件绑定相关的內联函数等其他标签最基本,最常用的脚本引入方式。 原文: http://pij.robinqu.me/Browser_Scripting/Document_Loading/ScriptExecution.html 源代码: https://github.com/RobinQu/Programing-In-J...

    firim 评论0 收藏0
  • 脚本化HTTP 取得响应 指定请求

    摘要:并且这个对象属性和方法允许指定请求细节和提取响应数据。此请求不会被缓存。在发送完成请求以后,下一步将会取得响应。 脚本化HTTP下面将会用js代码操纵HTTP下面将会说明在没有导致web浏览器重新加载任何窗口或者窗体的情况下,脚本实现web浏览器和服务器之间的通信。ajax:为一种找早起避免页面重载而动态更新页面的方式,不过现在是直接数据驱动,或者类似于vue的单页应用comet:这个...

    idisfkj 评论0 收藏0
  • 把JavaScript文件放在文档的头部还是尾部

    摘要:我们可以看到,百度也在头部引入了一些文件,这些文件引入的方式与的做法差不多,都在引入外部资源的标签上添加了属性,除了第一个文件没有那样做。 更好阅读体验,请访问dreamapple.me 我们今天来聊一聊关于JavaScript文件的引入位置的问题;大家在平时的Web开发中有没有想过这样一个问题,那就是我应该在文档的头部(也就是标签内部里面)引入所需要的JavaScript文件还是应该...

    TerryCai 评论0 收藏0
  • 拒绝js阻塞—defer、async作用区别分析

    摘要:阻塞原理浏览器内核可以分成两部分渲染引擎或者和引擎。等引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续和的构建。执行时,解析暂停。从加载完成立即执行来看,模式执行顺序与写的顺序无关,不保证执行顺序。 js阻塞原理 浏览器内核可以分成两部分:渲染引擎(Layout Engine 或者 Rendering Engine)和 JS 引擎。早期渲染引擎和 JS 引擎并没有十分明确的区分,但随...

    wuaiqiu 评论0 收藏0
  • 谈谈 <script> 标签以及其加载顺序问题,包含 defer & async

    摘要:标签加载顺序如果要谈标签加载顺序问题,首先要谈的就是标签的位置,因为标签的位置对于加载顺序来说有着很重要的影响。例如标签在以上代码中,可能由于下载时间比较长,由于两个标签都是异步执行,互不干扰,因此可能就会先于执行。 谈谈 标签加载顺序的问题 这篇文章比较长,如果你耐心读完了,我会感谢你愿意在这篇文章上花费时间,也希望你有收获。 其实说起,几乎搞前端的都知道他的作用:引入 JavaS...

    alexnevsky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<