JavaScript 运行机制之执行顺序详解
JavaScript是一种描述型脚本语言,它不同于 Java 或 C# 等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行。如果你不能理解 JavaScript 语言的运行机制,或者简单地说,你不能掌握 JavaScript 的执行顺序,那你就犹如伯乐驾驭不了千里马,让千里马脱缰而出,四处乱窜。
那么JavaScript是怎么来进行解析的吗?它的执行顺序又是如何的呢?在了解这些之前,我们先来认识几个重要的术语:
1、代码块
JavaScript中的代码块是指由<script>标签分割的代码段。例如:
|
1
2
3
4
5
6
|
<script type="text/javascript"> alert("这是代码块一");</script><script type="text/javascript"> alert("这是代码块二");</script> |
JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享。什么意思呢? 举个例子,你就明白了:
|
1
2
3
4
5
6
7
8
9
|
<script type="text/javascript"> alert(str);//因为没有定义str,所以浏览器会出错,下面的不能运行 alert("我是代码块一");//没有运行到这里 var test = "我是代码块一变量";</script><script type="text/javascript"> alert("我是代码块二"); //这里有运行到 alert(test); //弹出"我是代码块一变量"</script> |
上面的代码中代码块一中运行报错,但不影响代码块二的执行,这就是代码块间的独立性,而代码块二中能调用到代码一中的变量,则是块间共享性。
2、声明式函数与赋值式函数
JS中的函数定义分为两种:声明式函数与赋值式函数。
|
1
2
3
4
5
6
7
8
9
|
<script type="text/javascript"> function Fn(){ //声明式函数 } var Fn = function{ //赋值式函数 }</script> |
声明式函数与赋值式函数的区别在于:在JS的预编译期,声明式函数将会先被提取出来,然后才按顺序执行js代码。
3、预编译期与执行期
事实上,JS的解析过程分为两个阶段:预编译期(预处理)与执行期。
预编译期JS会对本代码块中的所有声明的变量和函数进行处理(类似与C语言的编译),但需要注意的是此时处理函数的只是声明式函数,而且变量也只是进行了声明但未进行初始化以及赋值。
|
1
2
3
4
5
6
7
8
9
10
|
<script type="text/javascript"> Fn(); //执行结果:"执行了函数2",同名函数后者会覆盖前者 function Fn(){ //函数1 alert("执行了函数1"); } function Fn(){ //函数2 alert("执行了函数2"); }</script> |
|
1
2
3
4
5
6
7
8
9
10
|
<script type="text/javascript"> Fn(); //执行结果:"执行了声明式函数",在预编译期声明函数及被处理了,所以即使Fn()调用函数放在声明函数前也能执行。 function Fn(){ //声明式函数 alert("执行了声明式函数"); } var Fn = function(){ //赋值式函数 alert("执行了赋值式函数"); }</script> |
|
1
2
3
4
5
6
7
8
9
10
|
//代码块一<script type="text/javascript"> alert(str);//浏览器报错,但并没有弹出信息窗</script>//代码块二<script type="text/javascript"> alert(str); //弹窗"undefined" var str = "aaa";</script>//js在预处理期对变量进行了声明处理,但是并没有进行初始化与赋值,所以导致代码块二中的变量是unfiened的,而代码一中的变量是完全不存在的,所以浏览器报错。 |
理解了上面的几个术语,相信大家对JS的运行机制已经有了个大概的印象了,现在我们来看个例子:
|
1
2
3
4
5
6
7
8
|
<script type="text/javascript"> Fn(); //浏览器报错:"undefined"</script><script type="text/javascript"> function Fn(){ //函数1 alert("执行了函数1"); }</script> |
为什么运行上面的代码浏览器会报错呢?声明函数不是会在预处理期就会被处理了吗,怎么还会找不到Fn()函数呢?其实这是一个理解误点,我们上面说了JS引擎是按照代码块来顺序执行的,其实完整的说应该是按照代码块来进行预处理和执行的,也就是说预处理的只是执行到的代码块的声明函数和变量,而对于还未加载的代码块,是没法进行预处理的,这也是边编译边处理的核心所在。
现在,让我们来总结整理下:
step 1. 读入第一个代码块。
step 2. 做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到step5。
step 3. 对var变量和function定义做“预编译处理”(永远不会报错的,因为只解析正确的声明)。
step 4. 执行代码段,有错则报错(比如变量未定义)。
step 5. 如果还有下一个代码段,则读入下一个代码段,重复step2。
step6. 结束。
而根据HTML文档流的执行顺序,需要在页面元素渲染前执行的js代码应该放在<body>前面的<script>代码块中,而需要在页面元素加载完后的js放在</body>元素后面,body标签的onload事件是在最后执行的。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<script type="text/javascript"> alert("first"); function Fn(){ alert("third"); }</script><body onload="Fn()"> </body><script type="text/javascript"> alert("second");</script> |
本文链接:http://www.cnblogs.com/oooweb/p/javascript-run-order.html
JavaScript 运行机制之执行顺序详解的更多相关文章
- javascript运行机制之执行顺序详解(转)
转自http://www.admin10000.com/document/3385.html JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言, ...
- javascript运行机制之执行顺序详解
1.代码块 指的的是有标签分割的代码段. 例如: <script type="text/javascript"> alert("这是代码块一"); ...
- Unity 继承MonoBehaviour脚本 执行顺序 详解
先看结果 Awake ->OnEnable-> Start ->-> FixedUpdate-> Update -> LateUpdate ->OnGUI ...
- javascript 执行顺序详解
JavaScript是一种描述 型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.如果你不能理解javaScript 语言的运行机制,或者简 ...
- React生命周期执行顺序详解
文章内容转载于https://www.cnblogs.com/faith3/p/9216165.html 一.组件生命周期的执行次数是什么样子的??? 只执行一次: constructor.compo ...
- jvm运行机制和volatile关键字详解
参考https://www.cnblogs.com/dolphin0520/p/3920373.html JVM启动流程 1.java虚拟机启动的命令是通过java +xxx(类名,这个类中要有mai ...
- 【Node.js】Event Loop执行顺序详解
本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...
- async/await 执行顺序详解
随着async/await正式纳入ES7标准,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 ...
- Python装饰器执行顺序详解
探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会 ...
随机推荐
- [2017BUAA软工]第3次个人作业
软工第3次个人作业--案例分析 一. 调研,评测 1.软件的bug(至少两个,不少于40字) 测试软件: 必应词典移动端 测试平台:iPhone 6 bug1 对于翻译功能中的图片翻译功能,必应词典是 ...
- Scrum Meeting Beta - 9
Scrum Meeting Beta - 9 NewTeam 2017/12/8 地点:新主楼F座二楼 任务反馈 团队成员 完成任务 计划任务 安万贺 解决离线状态下启动时报错的问题Issue #15 ...
- charles使用教程 干货~
大部分内容来自前辈们的摘写,博客园是怎么去转载其他好的博呢~ 言归正传,教程看过后还是自己再来一遍理解和操作才会更加深刻. Charles 是在 Mac/WIN下常用的网络封包截取工具,在做移动开发时 ...
- HDU 1231 最大子序列
http://acm.hdu.edu.cn/showproblem.php?pid=1231 Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连 ...
- By.cssSelector定位元素一个不足发现
这个如果用cssSelector定位,代码如下,此时输出的数值是0 System.out.println(driver.findElements(By.cssSelector("div[c ...
- multi thread for Java
I try to do a testing for HashTable Sychronized behavior today. As an Sychronized Object, HashTable ...
- Redis在Windows环境下单机安装及远程访问方案
一.下载Windows版Redis 打开https://github.com/MicrosoftArchive/redis/tags地址,找到最新版Redis安装包(Redis-x64-3.2.100 ...
- Codechef_JULY14
感觉这套比赛题目比较容易,没有以前做过的某次codechef那么凶残.题目还是很有意思的,最好的是有中文翻译. CSUB:签到题,直接从左往右扫一遍即可,维护前面出现过多少个1. #include & ...
- QML——添加自定义模块
一.模块的定义 在使用QML时,我们常常看到类似这样的语句: import QtQuick 2.0 import QtSensors 5.0 通过这些import语句,我们就能使用QML中的相关控件了 ...
- Ubantu下配置Sublime Text3---python环境的搭建
因为学习机器学习算法的原因,买的参考书籍很多都是python语言进行开发的,因此也想着在Linux系统下配置python的环境.Sublime是一款非常流行的编辑器,可以添加很多小巧有用的插件,同时也 ...