您的位置:首页 > Web前端 > JavaScript

JavaScript执行顺序

2016-06-08 20:36 309 查看
编写JavaScript代码时,总遇到运行顺序与所预想的不太一样。在此做一下总结,如若有什么意见请留言。

1. 变量的声明和引用

变量必须先声明后引用。

alert(myStr); // 弹出"undefined";
var myStr = "Hello World!";
alert(myStr); // 弹出"Hello World";


2. 函数的声明和引用

JavaScript是一种描述型脚本语言,有浏览器进行动态的解析与执行。

函数的定义方式有两种,浏览器对于不同的定义方式有着不同的解析顺序。

//“定义式”函数定义-函数声明语句(《JavaScript权威指南》对应名词)
function Fn1(){
alert("Hello World!");
}
//“赋值式”函数定义-函数定义表达式(《JavaScript权威指南》对应名词)
var Fn2 = function(){
alert("Hello wild!");
}
//此处采用《JavaScript权威指南》中的术语
    函数声明语句通常出现在JavaScript代码的最顶层,也可以嵌套在其他函数体内。但是在嵌套时,函数声明只能出现在所嵌套的函数的顶部。也就是说,函数定义语句不能出现在if语句,while循环等语句中。而且这种嵌套的移植性差。

    尽管函数声明语句和函数定义表达式包含相同的函数名,但是二者仍然不同。

相同点:这两种方式都创建了函数对象。
不同点:(1)函数声明语句中的函数名是一个变量名,变量指向函数对象。和通过var声明变量一样,都被显示地“提前”到了脚本或函数的顶部。因此他们在整个脚本和函数内都是可见的。(使用var的话,只有变量声明被提前了,但是初始化仍然在原来的位置),但是函数声明语句中函数名称和函数体均提前了(换而言之:脚本中的说有函数和函数中所有嵌套的函数都会在当前上下文中其他代码之前声明,即可以在声明之前进行调用。)(2)函数定义表达式则只能先声明后引用。

    页面加载过程中,浏览器会对页面上或载入的每个js代码块(或文件)进行扫描,如果遇到函数声明语句,则进行预处理(类似于C等的编译),处理完成之后再开始由上至下执行;遇到函数定义表达式,则只是将函数赋给一个变量,不进行预处理,待调用到的时候才进行处理。

//函数声明语句
Fn1();
function Fn1(){
alert("Hello World!");
}
/*
执行结果:正常弹出Hello World!
*/
//函数定义表达式
Fn2();
var Fn2 = function(){
alert("Hello wild!");
}
<pre name="code" class="javascript">/*
执行结果:没有弹出。查看浏览器的控制台,会发现已经报错,错误是:Uncaught TypeError: Fn2 is not a function
*/




3. 代码块及js文件的处理

浏览器对每个块或文件进行独立的扫描。(换而言之块与块之间,文件与文件之间是相互独立的),上面提到的函数声明语句不能跨代码块或者文件进行提前调用,必须按照块或文件(引用)的先后顺序,按照先声明在调用的原则引用。

<script type="text/javascript">
Fn();
</script>
<script type="text/javascript">
function Fn(){
alert("Hello World!");
}
</script>
// 报错:Uncaught ReferenceError: Fn is not defined,两个块换过来就对了


4. 重复定义函数会覆盖前面的定义

与众多编程语言语法类同。

易错点:

function fn(){
alert(1);
}
function fn(){
alert(2);
}
fn();
// 毫无疑问会弹出:“2”
如果提前调用,会如何呢?

fn();
function fn(){
alert(1);
}
function fn(){
alert(2);
}
// 还是弹出:“2”(首先解析,解析的时候第二个覆盖了第一个,所以最后执行的时候执行最后一个)


5. body的onload函数与body内部函数的执行

body内部的函数会先于onload的函数执行,测试代码:

//html head...
<script type="text/javascript">
function fnOnLoad(){
alert("I am outside the Wall!");
}
</script>
<body onload="fnOnLoad();">
<script type="text/javascript">
alert("I am inside the Wall..");
</script>
</body>
//先弹出“I am inside the Wall..”;
//后弹出“I am outside the Wall!”
body的onload事件触发条件是body内容加载完成,而body中的js代码会在这一事件触发之前运行

6.JavaScript是多线程or单线程?

JavaScript是单线程的,但是浏览器是多线程的。

function fn1(){
setTimeout(function(){
alert("我先调用")
},1000);
}
function fn2(){
alert("我后调用");
}
fn1();
fn2();
// 先弹出:“我后调用”,
// 1秒后弹出:“我先调用”
这里为什么会不按照顺序执行?

解析:看上去,fn2()和延时程序是分两个过程再走,但其实,这是JavaScript中的“回调”机制在起作用,类似于操作系统中的“中断和响应” —— 延时程序设置一个“中断”,然后执行fn2(),待1000毫秒时间到后,再回调执行fn1()。

同样,(5)中body的onload事件调用的函数,也是利用了回调机制——body加载完成之后,回调执行fnOnLoad()函数。

延时执行、Ajax异步加载也都是这个道理。

7. 回调函数

回调函数:类似于操作系统中的“中断和响应” —— 延时程序设置一个“中断”。

最常见的回调就是onclick、onmouseover、onmousedown、onload等等浏览器事件的调用函数;还有Ajax异步请求数据的处理函数;setTimeOut延时执行、setInterval循环执行的函数等。

参考资料:

JavaScript程序执行顺序问题总结

********************************************************************************结束语********************************************************************************************

  我在写这篇博客的时候也是一名初学者,有任何疑问或问题请留言,或发邮件也可以,邮箱为:577328725@qq.com,我会尽早的进行更正及更改。

在我写过的博客中有两篇博客是对资源的整理,可能对大家都有帮助,大家有兴趣的话可以看看!!
下载资料整理——目录:http://blog.csdn.net/fanxiaobin577328725/article/details/51894331

  这篇博客里面是我关于我见到的感觉不错的好资源的整理,里面包含了书籍及源代码以及个人搜索的一些资源,如果有兴趣的可以看看,我会一直对其进行更新和添加。
优秀的文章&优秀的学习网站之收集手册:http://blog.csdn.net/fanxiaobin577328725/article/details/52753638

  这篇博客里面是我对于我读过的,并且感觉有意义的文章的收集整理,纯粹的个人爱好,大家感觉有兴趣的可以阅读一下,我也会时常的对其进行更新。

********************************************************************************感谢********************************************************************************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: