位置: 编程技术 - 正文

探析浏览器执行JavaScript脚本加载与代码执行顺序(浏览器工作机制)

编辑:rootadmin

推荐整理分享探析浏览器执行JavaScript脚本加载与代码执行顺序(浏览器工作机制),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:浏览器工作机制,浏览器的执行机制,浏览器及其运行机制,浏览器执行过程,探析浏览器执行的命令,探析浏览器执行过程,浏览器执行过程,探析浏览器执行的命令,内容如对您有帮助,希望把文章链接给更多的朋友!

本文主要基于向HTML页面引入JavaScript的几种方式,分析HTML中JavaScript脚本的执行顺序问题

1. 关于JavaScript脚本执行的阻塞性

JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析、渲染以及其他资源的下载都要停下来等待脚本执行完毕①。这一点是没有争议的,并且在所有浏览器中的行为都是一致的,原因也不难理解:浏览器需要一个稳定的DOM结构,而JavaScript可能会修改DOM(改变DOM结构或修改某个DOM节点),如果在JavaScript执行的同时还继续进行页面的解析,那么整个解析过程将变得难以控制,解析出错的可能也变得很大。

然而这里还有一个问题需要注意,对于外部脚本,还涉及到一个脚本下载的过程,在早期的浏览器中,JavaScript文件的下载不仅会阻塞页面的解析,甚至还会阻塞页面其他资源的下载(包括其他JavaScript脚本文件、外部CSS文件以及图片等外部资源)。从IE8、firefox3.5、safari4和chrome2开始允许JavaScript并行下载,同时JavaScript文件的下载也不会阻塞其他资源的下载(旧版本中,JavaScript文件的下载也会阻塞其他资源的下载)。

注:不同浏览器对于同一个域名下的最大连接数有不同的限制,HTTP1.1协议规范中的要求是不能高于2个,但是大多数浏览器目前实际提供的最大连接数都多于2个,IE6/7都是2个,IE8提升到了6个,firefox和chrome也是6个,当然这个设置也是可以修改的,详细内容可以参考: 关于脚本的执行顺序

浏览器是按照从上到下的顺序解析页面,因此正常情况下,JavaScript脚本的执行顺序也是从上到下的,即页面上先出现的代码或先被引入的代码总是被先执行,即使是允许并行下载JavaScript文件时也是如此。注意我们这里标红了"正常情况下",原因是什么呢?我们知道,在HTML中加入JavaScript代码有多种方式,概括如下(不考虑requirejs或seajs等模块加载器):

(1)正常引入:即在页面中通过<script>标签引入脚本代码或者引入外部脚本

(2)通过document.write方法向页面写入<script>标签或代码

(3)通过动态脚本技术,即利用DOM接口创建<script>元素,并设置元素的src,然后再将元素添加进DOM中。

(4)通过Ajax获取脚本内容,然后再创建<script>元素,并设置元素的text,再将元素添加进DOM中。

(5)直接把JavaScript代码写在元素的事件处理程序中或直接作为URL的主体,示例如下:

第5种情况对于我们讨论的脚本执行顺序没有什么影响,因此我们这里只讨论前四种情况:

2.1 正常引入脚本时

正常引入脚本时,JavaScript代码会按照从上到下的顺序执行,不管脚本是不是并行下载,执行时还是按照引入的顺序从上到下执行的,我们以下面的DEMO为例:

首先,通过PHP写了一个脚本,这个脚本接收两个参数,文件URL和延迟时间,脚本会在传入的延迟时间之后,将文件内容发送给浏览器,脚本如下:

另外我们还定义了两个JavaScript文件,分别为1.js和2.js,在这个例子中,二者的代码分别如下:

1.js

alert("我是第一个脚本");

2.js

alert("我是第二个脚本");

然后,我们在HTML中引入脚本代码:

虽然第一个脚本延迟了3秒才会返回,但是在所有浏览器中,弹出的顺序也都是相同的,即:"我是第一个脚本"->"我是内部脚本"->"我是第二个脚本"

2.2 通过document.write向页面中写入脚本时

document.write在文档流没有关闭的情况下,会将内容写入脚本所在位置结束之后紧邻的位置,浏览器执行完当前短的代码,会接着解析document.write所写入的内容。

注:document.write写入内容的位置还存在一个问题,加入在<head>内部的脚本中写入了<head>标签内部不应该出现的内容,比如<div>等内容标签等,则这段内容的起始位置将是<body>标签的起始位置。

探析浏览器执行JavaScript脚本加载与代码执行顺序(浏览器工作机制)

通过document.write写入脚本时存在一些问题,需要分类进行说明:

[1]同一个<script>标签中通过document.write只写入外部脚本:

在这种情况下,外部脚本的执行顺序总是低于引入脚本的标签内的代码,并且按照引入的顺序来执行,我们修改HTML中的代码:

这段代码执行完毕之后,DOM将被修改为:

而代码执行的结果也符合DOM中脚本的顺序:"我是第一个脚本"->"我是内部脚本"->"我是第二个脚本"->"我是第一个脚本"

[2]同一个<script>标签中通过document.write只写入内部脚本:

在这种情况下,通过documen.write写入的内部脚本,执行顺序的优先级与写入脚本标签内的代码相同,并且按照写入的先后顺序执行:

我们再修改HTML代码如下:

在这种情况下,document.write写入的脚本被认为与写入位置处的代码优先级相同,因此在所有浏览器中,弹出框的顺序均为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是document.write写入的内部脚本"->"我是document.write写入的内部脚本"

[3]同一个<script>标签中通过document.write同时写入内部脚本和外部脚本时:

在这种情况下,不同的浏览器中存在一些区别:

在IE9及以下的浏览器中:只要是通过document.write写入的内部脚本,其优先级总是高于document.write写入的外部脚本,并且优先级与写入标签内的代码相同。而通过通过document.write写入的外部脚本,则总是在写入标签的代码执行完毕后,再按照写入的顺序执行;

而在其中浏览器中, 出现在第一个document.write写入的外部脚本之前的内部脚本,执行顺序的优先级与写入标签内的脚本优先级相同,而之后写入的脚本代码,不管是内部脚本还是外部脚本,总是要等到写入标签内的脚本执行完毕后,再按照写入的顺序执行。

我们修改以下HTML中的代码:

在IE9及以下的浏览器中,上面代码执行后弹出的内容为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是document.write写入的内部脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是第一个脚本"->"我是第一个脚本"

其他浏览器中,代码执行后弹出的内容为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是内部脚本"->"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是第一个脚本"->"我是document.write写入的内部脚本"

如果希望IE及以下的浏览器与其他浏览器保持一致的行为,那么可选的做法就是把引入内部脚本的代码拿出来,单独放在后面一个新的<script>标签内即可,因为后面<script>标签中通过document.write所引入的代码执行顺序肯定是在之前的标签中的代码的后面的。

2.3 通过动态脚本技术添加代码时

通过动态脚本技术添加代码的主要目的在于创建无阻塞脚本,因为通过动态脚本技术添加的代码不会立刻执行,我们可以通过下面的load函数为页面添加动态脚本:

但是通过动态脚本技术添加的外部JavaScript脚本不保证按照添加的顺序执行,这一点可以通过回调或者使用jQuery的html()方法,详细可参考: 通过Ajax注入脚本

通过Ajax注入脚本同样也是添加无阻塞脚本的技术之一,我们首先需要创建一个XMLHttpRequest对象,并且实现get方法,然后通过get方法取得脚本内容并注入到文档中。

代码示例:

我们可以用如下代码封装XMLHttpRequest对象,并封装其get方法:

然后基于xhr对象,再创建loadXhrScript函数:

我们上面的get方法添加了一个参数,即是否异步,那么如果我们采用同步方法,通过Ajax注入的脚本肯定是按照添加的顺序执行;反之,如果我们采用异步的方案,那么添加的脚本的执行顺序肯定是无法确定的。

轻松实现Bootstrap图片轮播 本文实例讲解了Bootstrap实现图片轮播的详细代码,分享给大家供大家参考,具体内容如下具体代码:!DOCTYPEhtmlhtmllang="en"headmetacharset="UTF-8"titleDocument/titlel

JavaScript继承模式粗探 真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继

基于JavaScript实现div层跟随滚动条滑动 在一个页面放2个悬浮框,悬浮框随页面的上下滚动有上下波动的效果,最终固定在同一位置效果展示如下所示:代码如下:!DOCTYPEhtmlhtmllang="en"headmetachar

标签: 浏览器工作机制

本文链接地址:https://www.jiuchutong.com/biancheng/383779.html 转载请保留说明!

上一篇:学习JavaScript设计模式之策略模式(javascript学习指南)

下一篇:轻松实现Bootstrap图片轮播(轻松实现财富自由)

  • 查补以前年度税款
  • 出口退税申报的发票无电子信息是什么意思
  • 应发工资包含请年假吗
  • 税控盘上报
  • 盈余公积未分配利润
  • 工业企业如何进行设备的选购管理
  • 换汇成本太低怎么处理?
  • 个人所得税如何申报
  • 车辆保险费包括
  • 业务有提成个税怎么扣
  • 道路运输业税率多少
  • 个人去税局开劳务费需要注意什么
  • 不同税率的产品可以开一张票里吗
  • 营改增试点实施办法的法律层次是
  • 面条适用的增值税率是
  • 房地产开发企业预收款预缴增值税
  • 企业自用房产出售怎么交税
  • 记账凭证做完之后干什么
  • 一直零申报会怎么样
  • 社保不计提会计分录
  • 苹果系统怎么修改开机密码
  • win10 0×0000007b怎么解决
  • 即征即退申报表如何填写
  • 个税申报晚了会退税费吗
  • css 栅格
  • 鸿蒙系统值得升级嘛
  • 计算机存储信息的基本单位是( )A字长B速度C内存D字节
  • 收到供应商现金怎么入账
  • 液晶显示器容易坏点
  • 完美解决索尼电视arc无声音
  • 最早的拍照手机是哪一年
  • php编程技术
  • 最小巧的单反相机
  • 打开苹果safari浏览器
  • 股东分红会计分录摘要
  • input输入框非空验证
  • typescript类型别名
  • php curlfile
  • php 后期静态绑定
  • php fopen()
  • php array_udiff_assoc 计算两个数组的差集实例
  • Laravel+jQuery实现AJAX分页效果
  • 个人福利要交税吗
  • 没有进项票开了销项票后期有了进项票可以吗
  • 财务应付
  • 个税系统中的离职怎么填
  • 固定资产报废该怎么处理
  • sqlserver分布式事务
  • 建筑业增值税是什么意思
  • 营业外支出账户核算的主要内容有
  • 哪些合同不需要缴纳印花税的通知
  • 一般纳税人增值税怎么做账务处理
  • 差旅费涉及的科目
  • 月末应交增值税借方余额期末该怎么处理
  • 海关进口增值税专用缴款书在哪里打印
  • 关税的计税方式一般可以分为
  • Mysql中LAST_INSERT_ID()的函数使用详解
  • 本地磁盘未响应怎么解决
  • win8资源管理器在哪
  • 电脑win7一开机就弹出各种广告窗口怎么办
  • 苹果发布新机老款能降多少
  • win8自启动
  • bootstrap 图表插件
  • JavaScript数组去重
  • 用jquery
  • 奇门遁甲实例详解
  • android通知消息
  • shell(bash)下“time” 命令的输出详解
  • unicode和utf–8 编码
  • 用bat调用exe并输入参数
  • 神奇宝贝
  • php 时间差
  • android新手入门
  • Do All in Cmd Shell一切在命令行下完成第1/6页
  • 只指定行网络什么意思
  • python按行读取文本并输出到excel
  • javascript如何
  • 国家税务总局财政部公告2023年第11号
  • 国家电子税务局江苏省电子税务局
  • 怎么使用企业级app
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设