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


    <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吧。

  • 相关阅读:
    汉诺塔学习笔记,有不正确的地方请小伙伴们指正~·~
    梯有N阶,上楼可以一步上一阶,也可以一步上二阶。编写一个程序,计算共有多少中不同的走法?
    HTTP Status 500
    java基础知识
    JAVA多线程和并发基础面试问答
    thymeleaf中的th:remove用法
    thymeleaf:局部变量 th:with
    springboot: thymeleaf 使用详解
    eclipse修改工作目录颜色
    The user specified as a definer ('root'@'%') does not exist
  • 原文地址:https://www.cnblogs.com/arxive/p/7516309.html
Copyright © 2020-2023  润新知