js执行顺序

本文探讨JavaScript的执行流程,包括单线程特性、onload事件及回调函数的应用。通过实例说明JavaScript如何处理多任务,解释了看似多线程现象背后的机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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

01 //html head...
02 <script type="text/javascript">
03 function fnOnLoad(){
04 alert("I am outside the Wall!");
05 }
06 </script>
07 <body onload="fnOnLoad();">
08 <script type="text/javascript">
09 alert("I am inside the Wall..");
10 </script>
11 </body>
12 //先弹出“I am inside the Wall..”;
13 //后弹出“I am outside the Wall!”

body的onload事件触发条件是body内容加载完成,而body中的js代码会在这一事件触发之前运行(为什么呢?6告诉你..)


6. JavaScript是多线程or单线程?
严格来说,JavaScript是没有多线程概念的,所有的程序都是“单线程”依次执行的。

举个不太恰当的例子:
01 function fn1(){
02 var sum = 0;
03 for(var ind=0; ind<1000; ind++) {
04 sum += ind;
05 }
06 alert("答案是"+sum);
07 }
08 function fn2(){
09 alert("早知道了,我就是不说");
10 }
11 fn1();
12 fn2();
13 //先弹出:“答案是499500”,
14 //后弹出:“早知道了,我就是不说”

那你肯定要问:那延时执行、Ajax异步加载,不是多线程的吗?没错,下面这样的程序确实看起来像“多线程”:

01 function fn1(){
02 setTimeout(function(){
03 alert("我先调用")
04 },1000);
05 }
06 function fn2(){
07 alert("我后调用");
08 }
09 fn1();
10 fn2();
11 // 先弹出:“我后调用”,
12 // 1秒后弹出:“我先调用”

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

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

Ajax请求中的数据处理函数也是一样的道理。

关于JavaScript线程问题的更深入讨论,看这篇 javascript中的线程之我见,以及infoQ上的 JavaScript多线程编程简介。

困了,再说一下回调函数吧。



7. 回调函数
回调函数是干嘛用的?就是回调执行的函数嘛,又废话:D

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

干脆我们写一个纯粹的回调函数玩:

01 function onBack(num){
02 alert("姗姗我来迟了");
03 // 执行num个耳光
04 }
05 function dating(hours, callBack){
06 var SP= 0; // SP,愤怒值
07 //女猪脚在雪里站了hours个钟头
08 //循环开始..
09 SP ++;
10 //循环结束...
11 callBack(SP);
12 }
13 dating(1, onBack);

dating运行完之后再执行回调函数onBack —— 约会结束了,暴风骤雨开始了。




=========================================================================================



虽然变量和函数声明可以在文档任意位置,但是良好的习惯应该是在所有JavaScript代码之前声明全局变量和函数,并对变量进行初始化赋值。在函数内部也是先声明变量,然后再引用。


按块执行JavaScript代码

所谓代码块就是使用<script>标签分隔的代码段。例如,下面两个<script>标签分别代表两个JavaScript代码块。

<script>

//JavaScript代码块1

vara=1;

</script>

<script>

//JavaScript代码块2

functionf(){

alert(1);

}

</script>

JavaScript解释器在执行脚本时,是按块来执行的。通俗地说,就是浏览器在解析HTML文档流时,如果遇到一个<script>标签,则JavaScript解释器会等到这个代码块都加载完后,先对代码块进行预编译,然后再执行。执行完毕后,浏览器会继续解析下面的HTML文档流,同时JavaScript解释器也准备好处理下一个代码块。

由于JavaScript是按块执行的,所以如果在一个JavaScript块中调用后面块中声明的变量或函数就会提示语法错误。例如,当JavaScript解释器执行下面代码时就会提示语法错误,显示变量a未定义,对象f找不到。

<script>

//JavaScript代码块1

alert(a);

f();

</script>

<script>

//JavaScript代码块2

vara=1;

functionf(){

alert(1);

}

</script>

虽然说,JavaScript是按块执行的,但是不同块都属于同一个全局作用域,也就是说,块之间的变量和函数是可以共享的。


1.6.4借助事件机制改变JavaScript执行顺序

由于JavaScript是按块处理代码,同时又遵循HTML文档流的解析顺序,所以在上面示例中会看到这样的语法错误。但是当文档流加载完毕,如果再次访问就不会出现这样的错误。例如,把访问第2块代码中的变量和函数的代码放在页面初始化事件函数中,就不会出现语法错误了。

<script>

//JavaScript代码块1

window.onload=function(){//页面初始化事件处理函数

alert(a);

f();

}

</script>

<script>

//JavaScript代码块2

vara=1;

functionf(){

alert(1);

}

</script>

为了安全起见,我们一般在页面初始化完毕之后才允许JavaScript代码执行,这样可以避免网速对JavaScript执行的影响,同时也避开了HTML文档流对于JavaScript执行的限制。

注意

如果在一个页面中存在多个windows.onload事件处理函数,则只有最后一个才是有效的,为了解决这个问题,可以把所有脚本或调用函数都放在同一个onload事件处理函数中,例如:

window.onload=function(){

f1();

f2();

f3();

}

而且通过这种方式可以改变函数的执行顺序,方法是:简单地调整onload事件处理函数中调用函数的排列顺序。

除了页面初始化事件外,我们还可以通过各种交互事件来改变JavaScript代码的执行顺序,如鼠标事件、键盘事件及时钟触发器等方法,详细讲解请参阅第14章的内容。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值