JS中函数执行顺序的问题?
链接:https://www.zhihu.com/question/23564807/answer/82996422
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行
如果你不能理解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>
JS中函数执行顺序的问题?的更多相关文章
- Promise对象及它在js中的执行顺序
关于Promise对象的学习及它的执行顺序 学习阮一峰老师的ES6入门后的记录 1.promise的定义 promise是一个对象,通常包裹着一个异步操作,promise对象提供一些接口的方法,返回一 ...
- php课程 1-3 web项目中php、html、js代码的执行顺序是怎样的(详解)
php课程 1-3 web项目中php.html.js代码的执行顺序是怎样的(详解) 一.总结 一句话总结:b/s结构 总是先执行服务器端的先.js是客户端脚本 ,是最后执行的.所以肯定是php先执行 ...
- JavaScript在页面中的执行顺序(理解声明式函数与赋值式函数) 转载
JavaScript在页面中的执行顺序 https://blog.csdn.net/superhoy/article/details/52946277 2016年10月27日 15:38:52 阅读数 ...
- [Vue]vue中各选项及钩子函数执行顺序
在vue中,实例选项和钩子函数和{{}}表达式都是不需要手动调用就可以直接执行的. 一.生命周期图示 二.vue中各选项及钩子函数执行顺序 1.在页面首次加载执行顺序有如下: beforeCreate ...
- 进阶学习js中的执行上下文
在js中的执行上下文,菜鸟入门基础 这篇文章中我们简单的讲解了js中的上下文,今天我们就更进一步的讲解js中的执行上下文. 1.当遇到变量名和函数名相同的问题. var a = 10; functio ...
- js中函数的参数为函数的情况即回调函数
js中函数的参数可以是数组对象也可以是函数,当参数为函数时我们叫做回调函数 //定义回调函数function B() { console.log("函数B")setTimeout( ...
- JS中函数参数和函数返回值的理解
函数本质就是功能的集合 JS中函数是对象,因此,函数名实际上仅仅是一个指向函数对象的指针,不会与某个函数绑定,所以,JS中没有重载(重载就是通过传递不同类型的参数,使两个相同函数名的函数执行不同的功能 ...
- js中的执行环境及作用域
最近在面试时被问到了对作用域链的理解,感觉当时回答的不是很好,今天就来说说js中的作用域链吧. 首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是JavaScript中最为重要的一个概念.执 ...
- 对JS中函数的理解
函数本质就是功能的集合 JS中函数是对象,因此,函数名实际上仅仅是一个指向函数对象的指针,不会与某个函数绑定,所以,JS中没有重载(重载就是通过传递不同类型的参数,使两个相同函数名的函数执行不同的功能 ...
随机推荐
- MySQL递归查询
MySQL8.0已经支持CTE递归查询,举例说明 CREATE TABLE EMP (EMPNO integer NOT NULL, ENAME ), JOB ), MGR integer, HIRE ...
- [工具推荐]002.SoftOrbits Sketch Drawer使用教程
SoftOrbits Sketch Drawer是一款简单易用的照片素描化软件,内置多种预设方案以及丰富的自定义细节. 只需要一次轻轻的鼠标点击,就可以帮助你迅速的将家人的照片转换为黑白或者彩色的素描 ...
- Pycharm虚拟环境的使用
Pycharm虚拟环境的使用 pycharm创建项目的时候,一定勾选inhert global site-packages.不然系统的库就没法用了. 打开Project Interpreters页面: ...
- 百万年薪架构师一文整理RabbitMQ、ActiveMQ、RocketMQ、Kafka
一般来说,大型应用通常会被拆分成多个子系统,这些子系统可能会部署在多台机器上,也可能只是一台机器的多个进程中,这样的应用就是分布式应用.在讨论分布式应用时,很多初学者会把它和集群这个概念搞混,因为从部 ...
- Mysql基础(三)
#DML语言 /* 数据操作语言 插入:insert insert into 表名(列名,...) values(值1,...); insert into 表名 set 列名=值, 列名=值,... ...
- CAD文件打印为PDF文档
标题: CAD文件打印为PDF文档 作者: 梦幻之心星 347369787@QQ.com 标签: [CAD, 打印, 转换] 目录: 软件 日期: 2019-5-28 目录 CAD文件打印为PDF文档 ...
- 泛微 e-cology OA 前台SQL注入
poc https://github.com/AdministratorGithub/e-cology-OA-SQL 用法:python elog_sql.py http://target 不存在返回 ...
- [01]HTML基础之简单介绍
1.前言 现如今科技进步,足不出户尽晓天下事,一转身便仿若隔世茫然.科技绽放时代,网络技术对人们的触变无疑是深远而重大的,隐于缤纷绚丽的网页背后,是前端的蜕变更新. 如今,随意点开页面,绚丽华彩的特效 ...
- layui插件croppers的使用
这是我第一次在layui环境下面使用croppers插件.先粘贴下前端代码并附上我的目录结构吧. @{ ViewData["Title"] = "Crop ...
- display有哪些值?说明他们的作用?
inline(默认)— 内联 none — 隐藏 block — 显示.块级元素(单独占一行) inline-block — 行内块元素(不占整行) table — 表格显示 list-item — ...