Javascript 词法分析

什么是词法分析?

先写个例子。

1
2
3
4
5
6
7
8
9
function t() {
var str = 123;
console.log(str); //33
console.log(str1); //undefined

var str1 = 11;

}

这里为什么,str1 的值,会是 undefined,因为JavaScript解释器在执行的时候有个词法分析的过程,词法分析的顺序决定了,这个值的事实结果。

那么词法分析的顺序是怎么样的呢?

1、先分析参数
2、再分析变量声明
3、最终分析函数声明

以下面的代码为例。

1
2
3
4
5
6
7
8

var age = 100;
function t(age) {
console.log(age);
}

t(5); //5

函数运行的瞬间,此函数会生成一个 Active Object,AO活动对象,一个函数作用于内能找到的所有变量,都在AO上。

分析结果: t.AO = {};

1、接收参数,以参数名为属性,参数值为属性值。

t.AO = {age:5};

2、 分析变量声明,在 AO 上形成一个属性,以变量名为属性名,值为undefined,如果 AO 上 已有同名属性,则不做任何影响。没有就略过。

3、分析函数声明,没有就略过。

最终:t.AO = {age:5};

如果函数的参数和函数内部定义的变量重名,会怎么样呢?

1
2
3
4
5
6
7
8

function t(age) {
var age = 5;
console.log(age);
}

t(11); // ???

这个值的事实结果是 5 ,为什么会这样?我们前面不是说到,如果 AO 上有同名属性,这里不做任何影响的吗?原因在于,这里是分析过程,实际执行中,age = 5 这是一个赋值操作。

1
2
3
4
5
6
7
8
9
10
11
12
13

// 分析
function t(age) {
var age = 5;
console.log(age);
}

t.AO.age = 5; //函数内部历经了一个赋值操作

//执行结果
t(11); // 5


再进一步,如果同名的是一个函数呢?

1
2
3
4
5
6
7
8
9
10
11

function t(greet) {
console.log(greet);

function greet() {
alert('wanhai');
}
}

t(3); //???

可能你会以为是 3 ,其实,事实结果是 greet 函数,为什么呢?还是从词法分析来解释。

函数运行的瞬间,此函数会生成一个 Active Object,AO活动对象,一个函数作用于内能找到的所有变量,都在AO上。

分析结果: t.AO = {};

1、接收参数,以参数名为属性,参数值为属性值。

t.AO = {greet:3};

2、分析变量声明,没有略过。

3、分析函数声明,AO上如果有与此函数同名的属性,则会被此函数覆盖。

1
2
3

t.AO.greet = function greet() {alert('wanhai');}

如果再进一步呢?比如把这里的函数声明,变成函数表达式

1
2
3
4
5
6
7
8
9
10
11

function t(greet) {
console.log(greet)
var greet = function() {
alert('wanhai');
}

}

t(3); //??

这个函数的结果是 3 ,为什么?还是用前面的步骤来分析。

0、函数运行的瞬间,此函数会生成一个 Active Object,AO活动对象,一个函数作用于内能找到的所有变量,都在AO上。

1、接收参数,以参数名为属性,参数值为属性值。

t.AO = {greet:3}

2、分析变量声明,发现AO存在greet属性,不做任何影响。 t.AO = {greet:3}

3、分析函数声明,没有略过。

所以,结果为 3.

但是如果,改成这样

1
2
3
4
5
6
7
8
9
10
11

function t(greet) {
var greet = function() {
alert('wanhai');
}
console.log(greet);

}

t(3); //??

结果是 function ,因为这里的AO对象已经被改变。

再来看一个例子。

1
2
3
4
5
6
7
8
9
10
11

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

a(1);

分析外层,a 函数

a.AO = {}
1 、分析参数,a.AO = {b:1}
2、分析var,略过
3、分析函数声明,a.AO = {b:function (b){alert(b)}};

执行

alert(b); a.AO.b = function(){}

分析内层 b 函数

b.AO = {}
1 、分析参数,略过
2、分析var,略过
3、分析函数声明,略过

alert(b);b.AO = {};

因为 b函数的 AO 对象中没有这个值,所以,要向上在 a.AO 上去拿。

故结果,都是函数。

函数声明与函数表达式

函数声明与函数表达式,有两个方面的区别,一方面是函数表达式的优先级别会比函数声明高,另一个是函数表达式是有返回值的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

function t() {
alert('wanhai');
}

t(); //函数声明中,因为优先级别高,所以这里的 执行函数,不管放在函数声明的前面,还是后面都可以。


var a = function() {
alert('123');
}

a(); //而函数表达式,执行函数一定要放在表达式后面,不然会报错。