<script>标签的加载解析执行
转自原文 <script>标签的加载解析执行
看了很多网上的文章,都是大同小异。总结一下。内部原理还没有搞清楚,有机会再学习。
一、<script>标签的加载解析执行顺序
html页面中的<script>标签中的内容(直接写入或者引用外部文件都一样)是以顺序加载执行的,每个<script>标记内容可以当成一个独立的块,同步的情况下一个块加载解析然后执行完后才加载下一块。当然这时也会阻塞其他页面元素的加载。所以网上说的变量调用:
<script type="text/javascript">//<![CDATA[
alert(tmp); //输出 undefined
var tmp = '111';
alert(tmp); //输出 111
//]]>
</script>
还有函数调用:
<script type="text/javascript">//<![CDATA[
test(); //浏览器报错
//]]>
</script>
<script type="text/javascript">//<![CDATA[
test(); //输出 fun!
function test(){alert('fun!');}
//]]>
</script>
其实很简单,对于变量,在一个作用域中在变量声明前面使用变量,本来就是undifined(解析过程中已经知道有这个变量, 但没赋值,等到执行才赋值)。对于函数,同一块中可以,因为解析的时候已经知道有那个函数了,但是分在不同块中,当test 调用时,下面声明test函数的内容根本还没被加载进来,所以调用出错。
二、document.write ()问题
本来这样不就挺好吗。但是来个document.write就坑爹了。先摘一段网上的话::“输出写入到脚本文档所在的位置,浏览器解析完documemt.write()所在文档内容后,继续解析document.write()输出的内容,然后在继续解析HTML文档”。
测试过,在一个<script>标记中通过document.write()输出的内容会依次插到该标记的后面(动态加载)。但插入内容没有解析和执行, 解析执行还是按文档顺序下来,等到执行完documemt.write()所在的script标记的内容后再解析执行。但是这仅限于document.write 方式没有写入可引用的外部文件并且引入文件内不包含document.write时的情况。
关于引入外部文件与外部文件包含document.write参考自http://w3help.org/zh-cn/causes/BX9014。
例子见参考,内容大概就是:第一,当document.write方式引入的外部文件里面包含document.write写入流,IE 是在当前 SCRIPT 标记内所有的 document.write 向文档中输出内容完成后,再处理以 document.write 方式引入的 JS 文件内的 document.write 写入流。对于其他浏览器,则根据代码执行顺序依次处理 document.write 方式写入的内容(但测试过,外部文件中除document.write外的内容对于ie和firefox一样,是等到当前 SCRIPT 标记执行结束后才执行的)。第二,当使用 document.write 方式写入可引用的外部JavaScript 内容后,非 IE Opera 浏览器并不会立即更新 DOM 树。
对于第二点,我觉得恰好可以解释网上所说的一个问题(没有debug,原因最后说明),问题如下
document.write('<script type="text/javascript" src="test.js"><\/script>');
<script type="text/javascript">//<![CDATA[
alert("333"); //]]>
</script>
test.js的内容是:
var tmpStr = '111'; alert(tmpStr);
在Firefox和Opera中的弹出值的顺序是:111、222、变量保存值111、333
在IE中弹出值的顺序是:222、111、333, 同时浏览器报错:tmpStr未定义
原因可能是IE在document.write时,并未等待加载SRC中的Javascript代码完毕后,才执行下一行,所以导致222先弹出,并且执行到document.write(‘document.write(“变量保存值” + tmpStr)’)调用tmpStr时,tmpStr并未定义,从而报错。
但是我觉得原因不是这个,原因应该就是其他浏览器没有立即更新dom树。IE会在document.write('<script type="text/javascript" src="test.js"><\/script>')后更新dom树,此时dom树中引用test文件的<script>节点已存在,后续插入的<script>节点都会被插入在正在执行的<script>的后面,也就是引入test文件的<script>节点的前面。所以执行alert时test内容还没执行。而其他浏览器是当<script>的内容执行完毕后再更新dom树,所以document.write写入的内容是以顺序添加到包含他们的<script>后面的。当然这只是我个人理解,如果错误还请看到的人指出。
最后一个问题,对于使用document.write时出现的firefox和IE间的处理不一致,当我firefox用debug设断点调试(一步一步跳)时竟然变得跟IE一致了。像上面那个例子firefox断点调试时竟然tempStr也是notdefined,引入的文件没有跳进去。js我也是学得不久有懂的请赐教。
花了一天还没搞明白,真不知道去抠这些问题有没有价值,觉得还是少用document.write吧。
<script>标签的加载解析执行的更多相关文章
- 【JavaScript性能优化】------理解Script标签的加载和执行
1.script标签是如何加载的?当浏览器遇到一个 < script>标签时,浏览器会停下来,运行JavaScript代码,然后再继续解析.翻译页面.同样的事情发生在使用 src 属性加载 ...
- 动态script标签同步加载 ps:无打包编译,静态实现静态资源入口动态配置,无编译打包静态资源添加版本号
/**功能:创建动态标签加载css ,js文件,重点是js文件,利用onloading加递归实现动态标签的同步加载用法:在html文件body底部script内部声明并调用下列函数,obj中写要加载的 ...
- js——<script>标签的加载顺序
用了很久的JavaScript,今天突然就碰见了将一个js文件放在<head></head>与<body></body>标签中,一个不可以执行,一个可以 ...
- 【javascript】script标签的async异步解析
<script src="script.js"></script> 没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染 ...
- 重操JS旧业第一弹:Script与JS加载
不管js被包装成什么样子,最终交给浏览器执行的js都是原生的,都离不开原生js的原理. Script标签纸html中用来加载js的标签,我们知道js可以是来自外部,本地,或者内部一段代码,在这里只讨论 ...
- JavaScript 的性能优化:加载和执行
随着 Web2.0 技术的不断推广,越来越多的应用使用 javascript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题.而这个问题又因 ...
- 浏览器中Javascript的加载和执行
在刚学习Javascript时曾对该问题在小组内做个一次StudyReport,发现其中的基础还是值得分析的. 从标题分析,可以加个Javascript的加载和执行分为两个阶段:加载.执行.而加载即浏 ...
- 高性能JavaScript-JS脚本加载与执行对性能的影响
在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 脚本位置对性能的影响 优化页面加载性能的原则之一是将scri ...
- [转]JavaScript 的性能优化:加载和执行
原文链接:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/index.html?ca=drs- JavaScript 的性能优化: ...
随机推荐
- [Swift通天遁地]四、网络和线程-(9)上传图片并实时显示上传进度
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- display:none 和 hidden 区别
- 【转】Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...
- DetachedCriteria和Criteria的使用方法
DetachedCriteria和Criteria的使用方法 /* * 下载统计 * @return */ public String downloadStatistics(){ logger ...
- Object未定义
js加载时会在jquery中报Object未定义的错误? 原因: 页面和iframe页面中都引入了jquery 或者 是页面中包含iframe,并且在iframe没有完成加载前操作了iframe中的j ...
- 计组_IEEE754_练习题
IEEE754 阶码:移码:尾数:原码 一个规格化的32位浮点数x的真值可表示为: x=(-1)^s×(1. M) × 2^(E-127) e=E-127 其中尾数域 ...
- SYN(synchronous)TCP/IP
SYN(synchronous)是TCP/IP建立连接时使用的握手信号.在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息, ...
- CDR软件-CorelDRAW软件下载,618活动
618我有诚意,你呢? 不花钱的618,是残缺的618 给自己一个放肆shopping的机遇 活动力度不够大? 继续升级,终极体验 618疯狂倒计时! 同志们,如果你错过了之前的抢先购和升级活动 那么 ...
- centos安装指定mysql
mysql下载地址:http://repo.mysql.com/ nginx下载地址 我下载是这个 http://nginx.org/packages/centos/7/noarch/RPMS/ngi ...
- CAD动态绘制带面积周长的圆(com接口)
CAD绘制图像的过程中,画圆的情况是非常常见的,用户可以在控件视区点取任意一点做为圆心,再动态点取半径绘制圆. 主要用到函数说明: _DMxDrawX::DrawCircle 绘制一个圆.详细说明如下 ...