JavaScript:全面解析各种浏览器网页中的JS代码的执行顺序

JavaScript运行原理: 解析和执行代码 解析器将源代码解析成抽象语法树,执行环境管理代码的执行过程,而执行栈控制执行环境的顺序。执行环境是JavaScript代码执行的环境,它包含了代码运行时所需的所有变量、函数和外部环境的引用。每当执行到一个函数时,会创建一个新的执行环境,并将其推入执行栈(Execution Stack)。在理解JavaScript的运行原理之前,我们需要了解它的基本组成部分:解析器、执行环境和执行栈。当JavaScript代码开始执行时,主线程会创建一个全局执行环境,并将其推入执行栈。 阅读详情
src="http://p.alimama.com/code.php?t=2&i=mm_10003521_106784_109301&w=760&h=90&sz=11&bgc=FFFACD&bdc=FFFFFF&tc=000080&lc=000000&dc=000000" name="alimamaifrm" id="alimamaifrm" border="0" marginwidth="0" marginheight="0" scrolling="no" width="760" frameborder="0" height="90">
        近来我通过一些测试以全面的解析网页在各种浏览器中的JavaScript代码的执行顺序,在这儿做个记录。
        我们知道javaScript是一种解释型语言,他的执行是自上而下,但是各个浏览器对于至上而下的理解是有细微差别的,而代码的上下游也就是程序流又对于程序正确至关重要,所以我觉得有必要深入理解多个js块儿的执行顺序。

首先得知道有多少方法能把javaScript加入到页面中呢?常见下述的前2种,其实还有更多。
1.页面中直接引入外部js文件:<script src="my.js"></script>

2.页面中直接写如js片段<script>alert(1)</script>

3.在js中引入js文件document.write("<scr"+"ipt src='my.js'></scr"+"ipt>");
    注意:这时候"..</script>"必须拆成"</scr"+"ipt>",否则浏览器可能会把父js片段关闭掉,出错;
   
4.同样在js中引用其他js片段,document.write("<scr"+"ipt>alert(1)</scr"+"ipt>");
    你可能觉得这个并没有必要,既然已经在script中了还套一层干嘛?呵呵,怎么说也是一种写法,而且它具有其特殊的行为,稍后我们讨论到。

5.使用Ajax中的xmlHttpRequest结合eval()来引入js,我最早在Dojo的代码见到,写的详细些:
    var ajaxRequest = getXmlHttpRequest()//省去各个浏览器得到xmlHttpRequest的部门
    ajaxRequest.open("GET","my.js",false);//使用xmlHttpRequest对象Get方法的同步调用
    ajaxRequest.send(null);
    sJsFragment = ajax.responseText;//得到字符串为js片段
    eval(sJsFragment);//执行js片段
    注意:这里要求my.js即后来的sJsFragment内容得是非常规范的js,切没有//开头的注释,怎样检查js是否规范呢?去http://jslint.com/
   
6.无所不能的Dom方法,这个我最早在Yahoo的前端代码中见到,非常厉害,也写的详细些:
    var oScript = document.createElement("script");//创建一个Script元素
    oScript.src = "my.js";//制定src属性
    document.getElementsByTagName("head")[0].appendChild(oScript);
    说明:my.js的内容会在oScript加入到文档中之后获得并执行。仔细看下这段容易发现这个调用是异步的,可以在文档载入之后通过事件触发,我用它变通了一下,作为了xmlHttpRequest的Get方法在跨域取数时的替代,获得了很完美的效果,以后有机会专门写篇文。
   
六种不少吧,可能还会有吧,而且这几种之间还可能相互嵌套,变化无常。
其中1、2、4、6种方式引入的javaScript的执行顺序是非常自然的,随着页面的载入以及后续的事件触发,它们遵守先来后到、而其内部自上而下。

我们主要关注的是第3、4种引入js方法带来的问题
测试准备:
编写文件1.js内容只有一行:
    alert("1.1");
编写文件3.js内容只有一行:
    alert("3.1");
再编写test.html
    <html>
        <head>       
            <script>//按第2种方式引入的脚本
                document.write("<scr"+"ipt>alert(4.1);</scr"+"ipt>");//按第4种方式引入的第一个脚本
                alert(2.1);
                document.write("<scr"+"ipt>alert(4.2);</scr"+"ipt>");//按第4种方式引入的第二个脚本
                document.write("<scr"+"ipt src='3.js'></scr"+"ipt>");//按第3种方式引入的脚本
                document.write("<scr"+"ipt>alert(4.3);</scr"+"ipt>");//按第4种方式引入的第三个脚本
                alert(2.2);
            </script>
            <script src="1.js">//按第1种方式引入的脚本</script>
        </head>
        <body>
        </body>
    </html>

执行结果:
IE浏览器的alert顺序为:       4.1 - 2.1 - 4.2 - 4.3 - 2.2 - 3.1 - 1.1
FireFox浏览器的alert顺序为:  4.1 - 2.1 - 4.2 - 2.2 - 3.1 - 4.3 - 1.1
Opera浏览器的alert顺序为:    4.1 - 2.1 - 4.2 - 3.1 - 4.3 - 2.2 - 1.1

分析:
IE:把第3种方式引入的js文件放在当前脚本单元之后接着执行,把第4种方式引入的js当作宿主脚本单元的一部分,在内部其引入的位置执行。
Opera:把第3种和第4种方式引入的js都当作宿主脚本单元的一部分,在内部其引入的位置执行。
FireFox:第3种方式引入的js文件放在当前脚本单元之后接着执行;在宿主引入第3种脚本之前,把第4种方式引入的js当作宿主脚本单元的一部分,在内部其引入的位置执行;在宿主引入第3种脚本之后,把第4种方式引入的js当作单独的一个脚本块儿,在宿主脚本执行之后接着执行。FirefFox的这种做法是很不友好。

结论:
浏览器差别巨大,所以不要指望通过第3、4种方式引入的脚本在引入位置或者宿主脚本执行后执行,如果你要至少支持FireFox浏览器,那么通过这种逻辑控制程序流会有大麻烦,应该避免。

实例:
以发布Alimama的广告代码为例(google adsense、yahoo定向推广也一样)。
多数站CMS系统管理广告代码,常常需要js的方式来做代码调用。这样如果想通过一个js发布多块儿广告位就会出现麻烦,比如在一个js中:
第一种写法:
/发布第一块儿广告
var alimama_pid=xxxx_1;
document.write("<scr"+"ipt src='http://p.alimama.com/inf.js'></scr"+"ipt>");
//发布第二块儿广告
var alimama_pid=xxxx_2;
document.write("<scr"+"ipt src='http://p.alimama.com/inf.js'></scr"+"ipt>");
希望引入的js块和js文件按书写顺序执行,根据上述测试的结论,针对这个任务,IE和FireFox是得不到想要的结果的,Opera可以。

第二种写法:
//发布第一块儿广告
document.write("<scr"+"ipt>var alimama_pid=xxxx_1</scr"+"ipt>");
document.write("<scr"+"ipt src='http://p.alimama.com/inf.js'></scr"+"ipt>");
//发布第二块儿广告
document.write("<scr"+"ipt>var alimama_pid=xxxx_2</scr"+"ipt>");
document.write("<scr"+"ipt src='http://p.alimama.com/inf.js'></scr"+"ipt>");
仍然根据上述测试的结论,IE是得不到想要的结果的,Opera干得很漂亮,而且蹩脚的FireFox居然也可以。

再说一个关于setTimeout()控制程序流的问题
下面一段脚本在页面加载时执行
function fn(){
    alert("a");
}
alert(1);
window.setTimeout(fn,3000);
alert(2);

各种浏览器alert的顺序都是1 - 2 - a。
也就是说setTimeout()方法不会让程序流停止,等候指定时间后再执行其下的语句,而只是告诉浏览器要在指定时间后执行参数中的方法。所以在程序载入过程中,不要指望setTimeout来造成程序流等待。

最后再补充一下 网站页面js请慎用onload事件
[特殊字符]用Python爬取中国裁判文书网案例信息:从爬虫到数据可视化全流程实战(附代码) ✅ 分析裁判文书网的网页结构;✅ 自动化爬取案件信息;✅ 解析加密参数并获取数据;✅ 数据可视化图表输出;✅ 模块化构建爬虫系统。 阅读详情

相关推荐

VTK学习(入门级教程,包括安装和使用)~持续更新中

说明:研究QT+VTK有段时间了,准备把学到的东西分享给大家,这篇博客以VS+QT+VTK为主进行展开学习的。

HXX904的博客 4757

【前端浏览器原理】浏览器简介及JavaScript线程

浏览器中的JavaScript线程 文章目录浏览器中的JavaScript线程一、进程和线程什么是并行处理进程 VS 线程进程和线程之间的关系有以下4个特点二、单进程浏览器时代问题1:不稳定问题2:不流畅问题3:不安全三、多进程浏览器时代早期多进程架构⽬前多进程架构引出的问题四、定时器引发的思考Ⅰ-定时器真是定时执行的吗?Ⅱ-定时器回调函数是在分线程执行的吗?Ⅲ-定时器是如何实现的?五、JS是单线程的如果在执行JavaScript代码的过程中,有异步操作呢?为什么js要用单线程模式, 而不用多线程模式? 一

前端学习博客 1865

从0到1搭建StarRocks3.4.1存算一体架构(VM 虚拟机版)

本文详细介绍了如何在VM虚拟机上从零搭建StarRocks 3.4.1存算一体架构。首先阐述了StarRocks作为高性能分布式SQL数据仓库的优势,重点讲解了其存算一体架构的设计原理。随后提供完整的安装指南,包括环境准备(3台CentOS 8虚拟机配置)、网络互通验证、Java环境配置、软件包解压安装等关键步骤。文章特别详细说明了FE和BE节点的配置文件修改(fe.conf和be.conf)以及必要的防火墙端口开放配置。通过图文并茂的方式,帮助开发者和运维人员快速掌握StarRocks集群部署方法,为后续

小 tom的博客 1329

浏览器插件——从开发到部署全流程详解

插件部署

m0_57021623的博客 1万+

别再手动巡检了!vRealize Operations Manager 8.x 自动化报告配置全攻略(附模板下载)

本文详细介绍了如何利用vRealize Operations Manager 8.x实现自动化巡检报告配置,大幅提升虚拟化运维效率。通过模板定制、智能调度和自动分发等功能,帮助运维团队告别手动生成报告的繁琐工作,实现90%以上的时间节省。文章还提供了实用的配置技巧和最佳实践,助力企业构建高效的自动化报告系统。

weixin_33806859的博客 298

AutoCAD2014与ObjectARX开发环境搭建实战指南

本文提供了一份详细的AutoCAD2014与ObjectARX开发环境搭建实战指南。内容涵盖从AutoCAD2014、Visual Studio 2010及ObjectARX 2014 SDK的版本匹配与环境准备,到Wizard安装、编码问题解决、Visual Studio配置,并最终通过一个完整的绘图命令开发示例,手把手引导开发者创建并加载第一个可运行的ObjectARX插件,为后续深入开发奠定坚实基础。

weixin_28475533的博客 288

Chrome 89 更新 js 事件触发顺序,导致99%的文章都错了(包括MDN)

大家好,我是秋风。 嗯…我又来了,这次又是在…楠溪和的讨论中产生的问题。 那事情是怎么样的呢? 起因 最近楠溪在看事件相关的文章,然后就跑来和我讨论说以下代码的执行效果和网上的文章不一致,代码如下: <div> <button>123</button> </div> <script> var btn = document.querySelector('button'); var div = document.querySelector('

程序员秋风的博客 453

图像加密与解密(附matlab代码)

详细介绍了三种图像加密解密原理,并基于matlab开发了一套相应系统。

2440

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

无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。一个典型的例子就是在页面中使用document.write()。例如清单 1 清单 1...

axl---专心专注于web前端开发 376

Qt5.15.7编译报错问题汇总:python2安装环境导致的问题

导致编译生成的:RegExpJitTables.h文件大小为0。RegExpJitTables.h 能生成且大小不为0KB。可以看到,正确的python路径,执行编译路径后。再执行 configure XXX…尝试直接改,将其改为正确的路径。

MusicScore的博客 1439

矩阵理论与应用:数理经济学中的投入产出模型分析

1. 背景介绍 矩阵理论是现代数学中的一个重要分支,它在各个领域都有广泛的应用。其中,投入-产出模型是矩阵理论在经济学中的一种应用,它可以用来分析一个国家或地区的经济结构和发展趋势。本文将介绍投入-产出模型的基本概念和原理,并通过实例来说明其应用。 2. 核心概念与联系 投入-产出模型是一

AI天才研究院 1487

在谷歌浏览器中如何查看js代码在终端的运行结果、如何查看请求头信息

在谷歌浏览器中如何查看js代码在终端的运行结果、如何查看请求头信息1 如何查看js代码在终端的运行结果(如何打开终端)2 查看请求头信息 1 如何查看js代码在终端的运行结果(如何打开终端) 方法1:从html页面中进入谷歌浏览器,点击谷歌浏览器右上角三个点 点击更多工具 点击开发者工具 方法2:在浏览器页面空白处右击鼠标,点击检查 方法3:快捷键:shift+ctrl+j 上面三种方法都会显示以下信息:Elements:看到页面元素的样式等信息 Console:终端的输出信息,在这个地方可

橘猫吃不胖的博客 6728

1998年高教社杯全国大学生数学建模竞赛 B 题:《灾情巡视路线》真题解析与 MATLAB 解决方案

🏆 本文已收录于专栏:《滚雪球学数学建模(含历年真题)》,持续更新最新及历年数学建模竞赛资料,每篇内容力求做到“问题讲透、模型讲清、代码可用、论文可参考”,帮助你从零开始逐步建立完整的数学建模知识体系。

**My Coding Family** 883

js 程序执行与顺序实现详解

声明:这是转载的 原帖地址:http://www.jb51.net/article/36755.htm JavaScript是一种描述型脚本语言,由浏览器进行动态的解析与执行,浏览器对于不同的方式有不同的解析顺序,详细介绍如下,感兴趣的朋友可以参考下哈 函数的声明和调用  JavaScript是一种描述型脚本语言,由浏览器进行动态的解析与执行。函数的定义方式大体有以下两种,浏览

bruce_sky的专栏 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

JavaScript运行命令

前言 动人js一段时间,我认为事情仅仅是一个很肤浅的理解。是非常欠缺的。所以開始使用博客来对这一部分的知识做个慢慢的记录和积累。相信积少成多,慢慢的将这一部分的知识攻克! 第一篇记录的不是相关的应用。而是非常底层的知识---JavaScript解析引擎。想要了解这一部分的知识也是通过在项目中遇到的问题而联想到的。 问题的背景 在一段脚本...

weixin_30299709的博客 108

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

JS代码放在head与body中的区别

head:需调用、事件触发才执行 body:页面加载时执行,生成页面内容

likepotato的博客 290

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

关于用append()插入代码后对应的js无效问题

因为JS代码执行的时候,选择器找到的元素是最开始的那一部分。 通过JS脚本新创建的元素,在之前JS代码执行的时候还不存在,所以JS代码中关于新创建元素的部分无效。 将对应的JS代码放在最下面就好了 (我遇到的情况是append()插入代码导致js文件失效,将关联JS的代码放到最下面就OK了 )

wang1994daren的博客 4790

js在html中加载顺序,html js文件加载顺序

打开一个网站,加载顺序是什么?先加载HTML然后JS然HTML页面加载和解析流程 : 1. 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请CSS布局HTML小编今天和大家分享,服务器返回html文件。 2. 浏览器开始载入html代码,发现标签内有一个标签引用外部CSS文件。 3. 浏览器又发出CSS文件的请CSS布局HTML小编今天和大家分享。小白CSS布局HTML...

weixin_39867142的博客 1156

【问答】浏览器如何编译前端代码?

浏览器如何编译前端代码

renqq001的博客 707

js在html中的加载顺序

1.加载顺序:引入标记<script />的出现顺序, 页面上的Javascript代码是HTML文档的一部分,所以Javascript在页面装载时执行的顺序就是其引入标记<script />的出现顺序,  <script />标记里面的或者通过src引入的外部JS,都是按照其语句出现的顺序执行,而且执行过程是文档装载的一部分。 DOCTYPE html PUBLIC "-//W3

yuntaowuhai的专栏 473

js文件的装载和执行

1.浏览器对script引用的js文件分两步,下载,下载完毕后马上执行;这两步都会阻塞浏览器继续解析。 2.加入defer属性,<scriptdefertype="text/javascript"src="some.js"></script>,浏览器会异步加载js,待DOMContentLoaded后顺序执行js。 3.预加载js,自定义执行时机。 <script language="javascript" type="text/javascript"&gt...

包磊磊的博客 533

javascript中的延迟脚本技术

javascript中的延迟脚本技术 defer:作用脚本在执行时,脚本会延迟到整个页面都解析完毕后在运行。

技术何 858

JavaScript文件引入方式区别

1、JavaScript文件引入方式 (1)正常引入 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> (2)defer <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js" defer="...

Haines 548

javascript简介

从今天开始,要认真学习javascript啦。接下来将有一系列的关于javascript的学习笔记。 day1. javascript简介 先大致了解下所谓的javascript,如下图: javascript的实现主要由三个部分组成,即ECMAScript、文档对象模型以及浏览器对象模型。 ECMAScript ECMAScript是javascript的

neverland-7 1083

javascript标签在页面中的位置探讨

在制作网页的过程中,我们经常写类似下面的代码: [html] 复制代码 代码如下: Example HTML Page Example HTML Page 按照惯例,所有的元素都应该放在页面的元素中。请注意:无论引用几个外部js文件,浏览器都会按照元素在页面中出

螺丝钉学习宝库 293
上一篇: 设置location.hash的值,前面不要带#号,为了兼容Safari
下一篇: JavaScript:网站页面js请慎用onload事件
lenel
博客等级 码龄20年 13粉丝 32原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值