转自原文 <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,原因最后说明),问题如下


<script type="text/javascript">//<![CDATA[
        document.write('<script type="text/javascript" src="test.js"><\/script>');       
   document.write('<script type="text/javascript">');       
    document.write('alert("222");')       
    document.write('alert("变量保存值" + tmpStr);');       
    document.write('<\/script>');        //]]>
</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>标签的加载解析执行的更多相关文章

  1. 【JavaScript性能优化】------理解Script标签的加载和执行

    1.script标签是如何加载的?当浏览器遇到一个 < script>标签时,浏览器会停下来,运行JavaScript代码,然后再继续解析.翻译页面.同样的事情发生在使用 src 属性加载 ...

  2. 动态script标签同步加载 ps:无打包编译,静态实现静态资源入口动态配置,无编译打包静态资源添加版本号

    /**功能:创建动态标签加载css ,js文件,重点是js文件,利用onloading加递归实现动态标签的同步加载用法:在html文件body底部script内部声明并调用下列函数,obj中写要加载的 ...

  3. js——<script>标签的加载顺序

    用了很久的JavaScript,今天突然就碰见了将一个js文件放在<head></head>与<body></body>标签中,一个不可以执行,一个可以 ...

  4. 【javascript】script标签的async异步解析

    <script src="script.js"></script> 没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染 ...

  5. 重操JS旧业第一弹:Script与JS加载

    不管js被包装成什么样子,最终交给浏览器执行的js都是原生的,都离不开原生js的原理. Script标签纸html中用来加载js的标签,我们知道js可以是来自外部,本地,或者内部一段代码,在这里只讨论 ...

  6. JavaScript 的性能优化:加载和执行

    随着 Web2.0 技术的不断推广,越来越多的应用使用 javascript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题.而这个问题又因 ...

  7. 浏览器中Javascript的加载和执行

    在刚学习Javascript时曾对该问题在小组内做个一次StudyReport,发现其中的基础还是值得分析的. 从标题分析,可以加个Javascript的加载和执行分为两个阶段:加载.执行.而加载即浏 ...

  8. 高性能JavaScript-JS脚本加载与执行对性能的影响

    在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 脚本位置对性能的影响 优化页面加载性能的原则之一是将scri ...

  9. [转]JavaScript 的性能优化:加载和执行

    原文链接:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/index.html?ca=drs- JavaScript 的性能优化: ...

随机推荐

  1. 马拉车算法(Manacher's Algorithm)

    这是悦乐书的第343次更新,第367篇原创 Manacher's Algorithm,中文名叫马拉车算法,是一位名叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,神奇之处 ...

  2. ACM_Alien And Password

    Alien And Password Time Limit: 2000/1000ms (Java/Others) Problem Description: Alien Fred wants to de ...

  3. 什么是mycat?

    Mycat关键特性 关键特性 支持SQL92标准 支持MySQL.Oracle.DB2.SQL Server.PostgreSQL等DB的常见SQL语法 遵守Mysql原生协议,跨语言,跨平台,跨数据 ...

  4. spring boot打包文件后,报错\No such file or directory

    现象: 一段代码: ClassLoader loader = XXXUtil.class.getClassLoader(); String jsFileName = loader.getResourc ...

  5. NHibernate系列学习(一)-看看用NH怎么做增速改查

    1.本次所有代码是在一下环境下运行的 学习系统:win8 64bit 开发环境:VS2013,MSSQL2012 NHibernate版本:NHibernate-4.0.3.GA [文章结尾有本次笔记 ...

  6. Mysql(三):多表查询和存储程序

    今天内容: ● 多表查询(内连接 外连接 子查询) ● 存储程序(存储过程 函数) 多表查询 ​ 同时从多张数据表中查取到需要的数据即是多表查询. 多表查询时,参与查询的表中每条数据进行组合,这种效果 ...

  7. synchronized关键字详解(二)

    synchronized关键字的性质 1.可重入:同一线程的外层函数获得锁之后,内层函数可直接再次获得该锁,好处:避免死锁,提升封装性 证明可重入粒度:1.同一个方法是可重入的 2.可重入不要求是同一 ...

  8. 关于 WebView 的一些笔记

    什么是 WebView WebView 是手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装的一个组件.没有提供地址栏和导航栏, WebView 只是单纯的展示一个网页界面.在开发中 ...

  9. mysql GTID主从复制(主库在线,添加新丛库)

    要求: 1.         主库上线,主库不停止服务的前提下做主从复制 2.         新添加一个丛库 操作: 1.         在主库导出数据(主库正常运行): 2.         将 ...

  10. Hive扩展功能(七)--Hive On Spark

    软件环境: linux系统: CentOS6.7 Hadoop版本: 2.6.5 zookeeper版本: 3.4.8 主机配置: 一共m1, m2, m3这五部机, 每部主机的用户名都为centos ...