js的执行过程

作者: 叫我徐小星 | 来源:发表于2016-03-29 13:54 被阅读962次

在网络的直言片语中禹禹前行,在书本的记录中逐步加深,然而只有在实践中才能提出疑问,才能映像深刻。


我所理解的js执行过程
1.按html文档流的顺序执行js代码

HTML文档在浏览器中的解析过程是这样的:浏览器是按着文档流从上到下逐步解析页面结构和信息的。JavaScript代码作为嵌入的脚本应该也算做HTML文档的组成部分,所以JavaScript代码在装载时的执行顺序也是根据脚本标签<script>的出现顺序来确定的;

2.预编译&执行

当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。

  1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。
  2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)
function Hello(){
  alert("Hello");
}
Hello();//Hello World

function Hello() {
  alert("Hello World");
}
Hello();//Hello World

会看到输出两次:Hello World
其实上面的一段代码其实被JS引擎预编译为这样的形式:

var Hello = function() {
  alert("Hello");
}
Hello = function() {
  alert("Hello World");
}
Hello();
Hello();

我们可以看到,其实函数也是数据,也是变量,我们也可以对“函数“进行赋值(重赋值)。

alert(a);//undefined    
var a=1;    
alert(a);   //1

:变量初始化过程发生在执行期,而不是预编译期。在执行期,JavaScript解释器是按着代码先后顺序进行解析的,如果在前面代码行中没有为变量赋值,则JavaScript解释器会使用默认值undefined。由于在第二行中为变量a赋值了,所以在第三行代码中会提示变量a的值为1,而不是undefined。

比较以下两段代码

f();  // 调用函数,返回值1    
function f(){    
    alert(1);    
} 
f(); // 调用函数,返回语法错误(缺少对象)    
var f= function(){    
    alert(1);    
} 

之所以结果不同是因为:在下面一段中,定义的函数仅作为值赋值给变量f,所以在预编译期,JavaScript解释器只能够为声明变量f进行处理,而对于变量f的值,只能等到执行期时按顺序进行赋值,自然就会出现语法错误,提示找不到对象f。

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

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

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

由于JavaScript是按块处理代码,同时又遵循HTML文档流的解析顺序,所以有时第一次执行代码会出现错误。但是当文档流加载完毕,如果再次访问就不会出现这样的错误。

<script>    
//JavaScript代码块1    
window.onload= function(){        // 页面初始化事件处理函数    
    alert(a);    
    f();    
}    
</script>    
<script>    
//JavaScript代码块2    
var a =1;    
functionf(){    
    alert(1);    
}    
</script>  

此时把访问第2块代码中的变量和函数的代码放在页面初始化事件函数中,就不会出现语法错误了。

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

以上包含了函数的声明前置,编译与预编译,我们知道正常的一段js代码都是先进性预编译,然后从上到下顺序执行。
后来偶然一次发现:

function A(){
...
}
function B(){
...
}
A();
B();

类似以上这样一段,通过断点发现有时候函数A没有执行完就开始执行函数B;当时百思不得其解,首先确认的是:js是不是顺序执行??得到的结果是。既然是,为什么会有时先执行B?后来旁边的实习生随意说了句:ajax的影响吧!顿时恍然大悟,我竟然忘了我的函数里面都用了ajax向后台异步请求数据,真是囧!

jq的ajax有两种方式:
同步:当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面出先假死状态,当这个AJAX执行完毕后才会继续运行其他代码页面假死状态解除。
异步:AJAX代码运行的时候其他代码一样可以运行。
async:false//同步
async:true//异步(默认)

相关文章

  • js的执行过程

    JavaScript是解释型语言,也就是说,我们的js代码会通过一个解释器来进行解释执行,这个解释器我们称为js引...

  • js的执行过程

    在网络的直言片语中禹禹前行,在书本的记录中逐步加深,然而只有在实践中才能提出疑问,才能映像深刻。 我所理解的js执...

  • JavaScript面向对象编程

    JS的解析与执行过程 全局预处理阶段执行阶段 函数预处理阶段执行阶段

  • 我的JS笔记 -- 执行上下文

    执行上下文,就是Js执行的时候的一个运行环境/作用域(scope)。执行上下文决定了Js执行过程中可以获取哪些变量...

  • 浏览器渲染原理

    HTML 的解析过程 js 的下载和执行会阻塞 HTML 的解析,等 js 执行完继续去解析 HTML 问题1:为...

  • JS的解析与执行过程

    总是感觉JavaScript的基础很差,说会也会说不会还真就不会,温故而知新,最近就开始复习起来,对解析与执行过程...

  • JS的解析与执行过程

    /* 今天学习了JS的解析与执行过程,感觉好牛逼,记录下来,以便日后复习 */ //一阶段 var a = 5; ...

  • 浏览器中的事件循环与Node中的事件循环

    浏览器中的事件循环 JS线程读取并执行JS代码 执行JS代码的过程中,指定异步的操作给对应的线程处理 异步线程处理...

  • 5.js引擎执行代码的过程

    先来看看js引擎执行代码的过程:代码执行分为两个过程,先是分析阶段(可以理解为执行准备阶段),然后是真正执行阶段。...

  • 19. JS的解析

    JS的解析 学习目标: 了解 定位js的方法 了解 添加断点观察js的执行过程的方法 应用 js2py获取js的方...

网友评论

  • eb9aaa2f5093:好文章,变量和函数提升的差别:变量先在预定义阶段设为undefined,执行阶段再赋值;函数则是在预定义阶段直接定义和赋值。非常好,受教了!
  • 一俢:喜欢
  • 我在睡觉:函数a没有执行完就执行函数b的说法不是很准确,函数a执行完了哦。异步的ajax请求立即返回了,ajax之下的函数语句也得到执行了,才执行b函数的。只是请求的响应还没有回来而已。👽
    叫我徐小星:@我在睡觉 谢谢你的提醒与热心。我会在这样的声音里越行越远 :blush:
    我在睡觉:@叫我徐小星 异步请求的话下面的代码是不应该访问返回数据的,访问数据的代码写在回调函数里。同步请求的话可以。你写代码实测一下吧,会加深理解。把浏览器调成龟速模式比较容易看出异步的效果
    叫我徐小星:@我在睡觉 也就是说ajax发送请求等待接收数据的时候会继续往下执行,所以请求发送成功后要调用的函数就不会立即执行,在接收数据的同时,代码也在继续往下,所以此期间如果用用到返回的数据的,都会是undefined吗?

本文标题:js的执行过程

本文链接:https://www.haomeiwen.com/subject/ejhslttx.html