JS代码运行过程简述(一)

JS 是动态语言,任何一段代码在执行以前都须要编译,它跟传统的语言不一样,它不是提早编译的,编译结果也不能在分布式系统中进行移植。
可是JS引擎进行编译的步骤和传统的编译语言很是类似,在某些环节可能比预想的要复杂。编程

传统的编译

  • 分词/词法分析(Tokenizing/Lexing)
    这个过程会将由字符串组成的字符串分解成(对编程语言来讲)有意义的代码块,这些代码块被称为词法单元(token)数组

e.g. var a = 2;
一般会被解析成var 、a、=、二、;
空格是否被当作此法单元,取决于空格在这门语言中是否具备意义编程语言

  • 解析/语法分析(Parsing)
    这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的表明了程序语法结构的树(抽象语法树,Abstract Syntax Tree, AST)分布式

var a = 2;函数

VariableDeclaration
|
|------ a
|------AssignmentExpression
    |-----2
  • 代码生成
    将AST转换成可执行代码的过程。this

var a = 2;
经过特定方法将var = 2;的AST转化为一组机器指令,用来建立一个叫做a的变量(包括内存分配等),并将一个值存储到a中。code

JS 编译

JS 的编译步骤和传统仍是很是类似的,只是某些环节比较复杂,这里我详细说一下“预编译”,其余三个步骤同传统的编译对象

  • 分词/词法分析(Tokenizing/Lexing)token

  • 解析/语法分析(Parsing)内存

  • 预编译
    首先先看一个例子:

function a(b) {    
      alert(b); 
    function b() {            
        alert(b);       
    }        
    b();    
}    
a(1);

答案先不说, 如今看具体的预编译过程:

  1. 预编译--全局
    1). 建立Global Object对象(GO)

2). 查找变量声明

-> 若是GO上尚未该属性,则添加该属性,值为undefined  
-> 若是GO上已经有该属性,则不作任何处理

3). 查找函数声明(eg. function foo () {})

-> 若是GO上尚未foo属性,则把函数赋值给foo属性  
 -> 若是GO上已经存在foo属性,则直接覆盖
  1. 预编译--函数
    1). 函数运行前的一瞬间,生成Activation Object(活动对象),简称AO

2). 分析参数

-> 把声明的参数造成AO的属性,值全为undefined  
 -> 接收实参,造成AO相应属性的值

3). 分析变量声明

-> 若是AO上尚未该属性,则添加该属性,值为undefined  
 -> 若是AO上已经有该属性,则不作任何处理

4). 分析函数声明(eg. function foo () {})

-> 若是AO上尚未foo属性,则把函数赋值给foo属性  
 -> 若是AO上已经存在foo属性,则直接覆盖
  • 代码生成
    JS执行过程简单的介绍完了,Do you get it?, 下面看以前例子分析:

function a(b) {    
      alert(b); 
    function b() {            
        alert(b);       
    }        
    b();    
}    
a(1);


// 分析以下
/*
 * 1. 建立GO对象(包含JS全局对象的内置对象Math、String、Date、etc)
 * 2. 查找变量声明,没有
 * 3. 查找函数声明,定义函数a, GO = {a: function () {}}
 * 4. 执行a(1)
 * // 如下为函数a运行前的编译
 * 5. 建立活动对象AO  AO={this, arguments}
 * 6. 分析形参 AO = {this, arguments, b: undefined}
 * 7. 接收实参 AO = {this, arguments, b: 1}
 * 8. 分析变量声明 AO = {this, arguments, b: 1}
 * 9. 分析函数声明 
     AO = {
         this
         argunments,
         b: function () {}
     }
 
 * // 执行
 * alert(b)  // function () { ... }
 * b()   // function () { ... }
 */

从以上分析很清晰就可以知道弹出两个function,是否是很简单啊。其实在执行b(),还有函数b也要编译哦,编译步骤同函数a,这里就不作分析了。
习题:

function a(b) {    
      alert(b); 
    b = function() {            
        alert(b);       
    }        
    b();    
}    
a(1);

本身试着分析一下,结果是1和function,你作对了么?难点:b = function () {}这个是一个赋值语句

相关文章
相关标签/搜索