转自原文 <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. 题解报告:hdu 1028 Ignatius and the Princess III(母函数or计数DP)

    Problem Description "Well, it seems the first problem is too easy. I will let you know how fool ...

  2. Android开发中的SQLite事务处理,即beginTransaction()方法

    使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTrans ...

  3. iOS- Size Class使用教程

    1:它引入了一种新的概念,抛弃传统意义上我们适配时所谓的具体宽高尺寸,把屏幕的宽和高分别分成两种情况:Compact-紧凑, Regular-正常(Any-任意,其实就是这2种的组合,所以我没分成3种 ...

  4. 3星|《IBM商业价值报告:区块链》:一些重要行业对区块链的态度和已经发生的区块链的应用

    区块链项目开发指南 (区块链技术丛书) 介绍IBM的专家们调研许多重要行业与组织后总结的各行业对区块链的态度和实际的应用.看起来有点意思,不过有两个缺点: 1:这些实际已经发生的应用基本没看到相关的新 ...

  5. PHP 之CURL请求封装GET、POST、PUT、DELETE

    /** * @Description: curl请求 * @Author: Yang * @param $url * @param null $data * @param string $method ...

  6. 基于python xlsxwriter、xlrd 生成测试报告

    import xlsxwriter,xlrd ''' 思路: 1.获取数据 2.整合数据 3.写入文件 ''' #筛选 def filt(category,table,filt_name=None,r ...

  7. 11.11如何卖到一个亿:从0到1的电商爆品打造术 电子书 PDF

    内容转自:https://download.csdn.net/download/chenyao1994/11191034 下载地址:https://pan.baidu.com/s/1uQ1cjm9QH ...

  8. Windows下Unity安装

    安装教程: https://www.paws3d.com/lesson/us-0101/ 问题1: 安装并完成注册后,在网页上能登录,但打开Unity时不能启动成功,一直停留在如下界面 解决方案:断网 ...

  9. include和require区别

    1.  include()执行的时候需要引用的文件每次都要进行读取评估; require()执行时需要引用的文件只处理一次(实际上执行时需要引用的文件内容替换了require()语句) 可以看出若有包 ...

  10. list.h在用户态下的应用

    一.背景 list.h文件位于linux/include下,内核中链表的操作函数都在其中.它有许多关于链表的操作函数,所以我们可以尝试将list.h拉到用户态中来使用,这样,我们在用户态中若要用到链表 ...