深入理解javascript的执行顺序


Posted in Javascript onApril 04, 2014

如果你不能理解javaScript语言的运行机制,或者简单地说,你不能掌握javascript的执行顺序,那你就犹如伯乐驾驭不了千里马,让千里马脱缰而出,四处乱窜。

那么JavaScript是怎么来进行解析的吗?它的执行顺序又是如何的呢?在了解这些之前,我们先来认识几个重要的术语:

1、代码块
JavaScript中的代码块是指由<script>标签分割的代码段。例如:

<script type="text/javascript">
      alert("这是代码块一");
</script>
<script type="text/javascript">
      alert("这是代码块二");
</script>

JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享。什么意思呢? 举个例子,你就明白了:

<script type="text/javascript">
      alert(str);//因为没有定义str,所以浏览器会出错,下面的不能运行
      alert("我是代码块一");//没有运行到这里
      var test = "我是代码块一变量";
</script>
<script type="text/javascript">
      alert("我是代码块二"); //这里有运行到
      alert(test); //弹出"我是代码块一变量"
</script>

上面的代码中代码块一中运行报错,但不影响代码块二的执行,这就是代码块间的独立性,而代码块二中能调用到代码一中的变量,则是块间共享性。

2、声明式函数与赋值式函数


JS中的函数定义分为两种:声明式函数与赋值式函数。

<script type="text/javascript">
     function Fn(){ //声明式函数     }
     var Fn = function{  //赋值式函数
     }
</script>

声明式函数与赋值式函数的区别在于:在JS的预编译期,声明式函数将会先被提取出来,然后才按顺序执行js代码。

3、预编译期与执行期

事实上,JS的解析过程分为两个阶段:预编译期(预处理)与执行期。

预编译期JS会对本代码块中的所有声明的变量和函数进行处理(类似与C语言的编译),但需要注意的是此时处理函数的只是声明式函数,而且变量也只是进行了声明但未进行初始化以及赋值。

<script type="text/javascript">
     Fn();  //执行结果:"执行了函数2",同名函数后者会覆盖前者
     function Fn(){ //函数1
        alert("执行了函数1");
     }     function Fn(){  //函数2
        alert("执行了函数2");
     }
</script>  
<script type="text/javascript">
      Fn();  //执行结果:"执行了声明式函数",在预编译期声明函数及被处理了,所以即使Fn()调用函数放在声明函数前也能执行。
      function Fn(){ //声明式函数
         alert("执行了声明式函数");
      }
      var Fn = function(){  //赋值式函数
         alert("执行了赋值式函数");
      }
</script>

//代码块一
<script type="text/javascript">
      alert(str);//浏览器报错,但并没有弹出信息窗
</script>
//代码块二
<script type="text/javascript">
      alert(str); //弹窗"undefined"
      var str = "aaa";
</script>
//js在预处理期对变量进行了声明处理,但是并没有进行初始化与赋值,所以导致代码块二中的变量是unfiened的,而代码一中的变量是完全不存在的,所以浏览器报错。

理解了上面的几个术语,相信大家对JS的运行机制已经有了个大概的印象了,现在我们来看个例子:

<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事件是在最后执行的。
<script type="text/javascript">
    alert("first");
    function Fn(){
     alert("third");
    }
</script>
<body onload="Fn()"></body>
<script type="text/javascript">
    alert("second");
</script>

 

Javascript 相关文章推荐
仿163填写邮件地址自动显示下拉(无优化)
Nov 05 Javascript
Jquery 基础学习笔记之文档处理
May 29 Javascript
关于使用 jBox 对话框的提交不能弹出问题解决方法
Nov 07 Javascript
JavaScript实现QueryString获取GET参数的方法
Jul 02 Javascript
JS实现一个列表中包含上移下移删除等功能
Sep 24 Javascript
jquery实现简单的遮罩层
Jan 08 Javascript
原生js实现可爱糖果数字时间特效
Dec 30 Javascript
JavaScript框架Angular和React深度对比
Nov 20 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
Apr 10 Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
Feb 08 Javascript
layui 数据表格+分页+搜索+checkbox+缓存选中项数据的方法
Sep 21 Javascript
react合成事件与原生事件的相关理解
May 13 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
Apr 04 #Javascript
原生js获取宽高与jquery获取宽高的方法关系对比
Apr 04 #Javascript
在jquery中的ajax方法怎样通过JSONP进行远程调用
Apr 04 #Javascript
javascript中的循环语句for语句深入理解
Apr 04 #Javascript
利用jquery动画特效和css打造的侧边弹出垂直导航
Apr 04 #Javascript
调试代码导致IE出错的避免方法
Apr 04 #Javascript
javascript写的一个模拟阅读小说的程序
Apr 04 #Javascript
You might like
php生成随机密码的三种方法小结
2010/09/04 PHP
PHP cdata 处理(详细介绍)
2013/07/05 PHP
PHP微信开发之查询城市天气
2016/06/23 PHP
PHP三种方式实现链式操作详解
2017/01/21 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
laravel 实现关闭CSRF(全部关闭、部分关闭)
2019/10/21 PHP
firefox插件Firebug的使用教程
2010/01/02 Javascript
左右悬浮可分组的网站QQ在线客服代码(可谓经典)
2012/12/21 Javascript
ztree获取当前选中节点子节点id集合的方法
2015/02/12 Javascript
ECMAScript6新增值比较函数Object.is
2015/06/12 Javascript
jQuery文件上传控件 Uploadify 详解
2016/06/20 Javascript
jQuery插件form-validation-engine正则表达式操作示例
2017/02/09 Javascript
微信小程序教程系列之视图层的条件渲染(10)
2017/04/19 Javascript
xmlplus组件设计系列之下拉刷新(PullRefresh)(6)
2017/05/03 Javascript
JS实现十字坐标跟随鼠标效果
2017/12/25 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
微信小程序JS加载esmap地图的实例详解
2019/09/04 Javascript
微信小程序报错: thirdScriptError的错误问题
2020/06/19 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
python实现的登录和操作开心网脚本分享
2014/07/09 Python
python机器学习之随机森林(七)
2018/03/26 Python
PyQt5每天必学之弹出消息框
2018/04/19 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
浅谈python累加求和+奇偶数求和_break_continue
2020/02/25 Python
基于zepto的插件之移动端无缝向上滚动并上下触摸滑动实例代码
2016/12/20 HTML / CSS
Electrolux伊莱克斯巴西商店:家用电器、小家电和配件
2018/05/23 全球购物
美国知名的旅游网站:OneTravel
2018/10/09 全球购物
文秘专业毕业生就业推荐信
2013/11/08 职场文书
《神奇的克隆》教学反思
2014/04/10 职场文书
省级青年文明号申报材料
2014/05/23 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
安全教育培训心得体会
2016/01/15 职场文书
祝福语集锦:送给毕业同学祝福语
2019/11/21 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers
详解Java七大阻塞队列之SynchronousQueue
2021/09/04 Java/Android