我理解的JavaScript预编译

JavaScript是一门单线程,解释型,弱类型的动态语言,解释一行执行一行。函数

JavaScript执行过程首先先语法分析,就是分析一遍代码有没有语法错误,解析期间不会执行代码。接着就开始预编译,预编译完了就开始一行一行执行代码。线程

预编译过程会建立两个对象,一个是全局的Global Object对象,简写GO,另外一个是函数的Activation Object对象,简写AO。两个只是做用域不一样,建立步骤是同样的。cdn

预编译大概步骤:对象

建立AO、GO对象ip

找形参和变量声明,做为属性名,值为undefined作用域

统一实参和形参it

找函数声明,赋值函数体io

说的抽象了,咱们以一个函数为例:console

function fn(a) {编译

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

建立AO = {}

把形参和变量声明做为属性名和赋值undefined

AO = {

a: undefined,//参数a var a function a

b: undefined,//var b

c :undefined,//function c

}

统一形参和实参

AO = {

a: 3,

b: undefined,//var b

c :undefined,//function c

}

找函数声明,赋值函数体

AO = {

a: function a(){},

b: undefined,//var b

c: function c(){},

}

接着就是一行一行执行了:

function fn(a) {

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

AO = {

a: function a(){},

b: undefined,

c: function c(){},

}

当执行第一个打印的时候,打印出function,而后var a = 1的时候,声明已经声明过了,其实就a = 1,因此第二个打印是1,到了声明函数a的时候已是声明过的,再打印也是1,至于b和c就不用多说了。最后结果就是f a(){}、一、一、f(){}。

其实能够记住几个点,函数声明是总体提高,变量声明只是声明提高。还有,若是一个变量没有声明,那么默认就是window的:

(function fn() {

var a = b = 10;

}());

console.log(b);//10

console.log(a);//err

b没有直接var声明,那么就是全局window的,因此b能打印,a就会报错。

有个点要注意,JavaScript在预编译阶段, 会解释函数声明, 但却会忽略表式。好比一个自执行函数:

(function fn() {

}())

当执行到有()的时候,JavaScript会去对这个表达式求解获得返回值,返回的是一个函数且有(),因此直接执行了,其它的自执行函数原理都是这样的,都是经过表达式。函数转换为表达式的方法并不必定要靠分组操做符(),咱们还能够用void操做符,!操做符+操做符等等。

+function () {}()

void(function () {alert(0)}())

console.log(function () {alert(0)}())

这些表达式均可以当即执行函数,就算+号获得的最终结果是NaN,可是在隐式转换以前却要先执行函数。

函数参数你能够看做在函数里面隐式的声明了一个变量a:

function fn(a) {

var a;

console.log(a);//3

}

fn(3)

并且函数参数里面在预编译过程当中,会造成一个临时做用域,在预编译完了以后会消失:

function fn(a, b = function () {a = 5}) {

console.log(a);//3

b();

console.log(a);//3

}

fn(3)

(a, b = function () {a = 5})这是一个临时的做用域,这里面的参数a就算改变了也影响不到原来的参数a。只有在参数做用域里面才有效果:

function fn(a, b = (function () {a = 5})()) {

console.log(a);//5

console.log(a);//5

}

fn(3)

相关文章
相关标签/搜索