词法分析步骤
JavaScript在运行前会有一个类似预编译的过程这个过程就是我们所说的词法分析。这个词法分析的步骤
- 分析参数
- 再分析变量的声明
- 分析函数说明
列子:
function func(age){
console.log(age); //f age(){}
var age = 27;
console.log(age); //27
function age(){}
console.log(age); //27
}
func(3)
JavaScript运行的时候遇到函数,会生成一个活动对象(Active Object),后面简称AO
第一步 分析形式参数:
当函数有形式参数的时候就会把实现 AO.age = undefined
当我们传入实参的时候就会把前面的覆盖 AO.age = 3;
第二步 分析局部变量
找到所有的局部变量然后从上到下一步一步的分析。
上面列子的var age = 27 开始因为词法分析所以把AO.age = undefined
所以几乎所有的局部变量都是AO.age = undefined形式。
所以AO.age = undefined
因为形式参数优先于局部变量,上面传入实参后AO.age = 3所以在这里AO里面的age属性值就是AO.age = 3
在这里要注意到形式参数的值在词法分析的时候优先于局部变量在这里AO里面的属性
第三步 分析函数声明表达式
当所有的局部变量分析完后我们开始分析函数声明表达式
上面的函数就会实现 AO.age = function()
又是因为上面有同样的属性所以就会覆盖上面的AO.age = undefined
所以最后AO.age = f age(){}
注意:上面函数声明表达式级别最高会覆盖前面相同的属性,然而局部变量和形式参数互不影响。
当我们调用函数的时候:
上面的这些词法分析做完以后得到AO.age = f age(){},
调用函数我们开始运行到第一行代码,让我们打印,所以第一个打印的就是 f age(){}
运行到var age = 27的时候这里age的值就是27.
在接下来我们要打印age的值所以第二个打印为 27
再到下面一行是一个函数表达式但是这个表达式没有运行所以不影响局部变量age的值这是age还是27。
所以第三个打印的还是27
这个就是上面函数从开始的词法分析,到最后的函数运行,再到后面的函数运行结果。
下面是一个代码会解释上面的
<script> function func(age){ console.log(age); //3 var age = 27; console.log(age); //27 } func(3) //在这我们可以看词法分析后的age=3也就是说形式参数优先于局部变量。 </script> <script> function func(age){ console.log(age); //f age(){} var age = 27; console.log(age); //27 function age(){} console.log(age); //27 var age = 66 } func(3) //上面我们可以看到当我们的局部变量在函数声明表达式后面的时候不 //会改变这个属性的值所以说函数声明表达式级别最高有他就会覆盖前面的 </script> <script> function func(){ console.log(age); //undefined var age = 27; console.log(age); //27 } func() //上面再进行词法分析的时候没有形式参数没有函数声明表达式所以最后得到的age=undefined </script>
示列1
<script> function func(age) { var age; console.log(age); //f age(){} var age = 23; console.log(age); //23 function age() {} console.log(age); //23 } func(28) </script>
开始词法分析
1、形式参数
开始 AO.age=undefined
传入实参后得到AO.age = 28
2、局部参数
因为有形式参数,所以这里的局部参数AO.age不发生改变。到这里A.age=28
3、函数声明表达式
这里可以得到AO.age=f age(){}
由于他的级别最高。所以词法分析后得到AO.age = f age(){}
函数调用执行阶段
执行到第一个log的时候:由于前面没有局部变量的赋值所以这个打印的就是开始的词法分析中变量的值: f age(){}
当执行到第二个log的时候:由于前面局部变量赋值所以会覆盖词法分析中的变量的值所以输出为 23
当执行到第三个log的时候:前面没有执行任何代码所以得到输出的值为23。
示列2
<script> function func(age) { var age; console.log(age); // f age() {console.log(age); } var age = 23; console.log(age); // 23 function age() { console.log(age) } age(); //报错说这个函数没定义 console.log(age); // } func(22) </script>
词法分析
这里就不详细分析了最后可以得到AO.age = f age(){}
执行阶段分析
var age: 这个只是声明下局部变量对我们词法分析的不影响这里age = f age(){console.log(age)}
console.log(age):所以直接打印f age(){}
var age = 23: 所以就会覆盖词法分析的age 所以这里的var age = 23;
console.log(age):由上面知道age = 23所以这里打印的是23
这一行是一个函数所以不执行,
age(): 由于前面我们定义了age为局部变量并且为他赋值了所以会报错说这不是一个函数
console.log(age):由上面知道var age = 23所以这里打印的是23
上面我们可以知道当我们定义函数的时候,在函数的前面如果声明一个和函数名一样的变量并且赋值,要不覆盖。我们可以这样理解一个JavaScript代码就是一个词法分析。当我们执行的时候在函数前面有一个一样的变量赋值那么我们在词法分析得到的这个函数对象就会被我们变量赋值所覆盖。因为执行的时候我们的函数是不执行的,只有在调用的时候才会执行。
<script> console.log(func); //f func(age) {var age;console.log(age);var age = 23;console.log(age);} var func=22; console.log(func); //22 function func(age) {var age;console.log(age);var age = 23;console.log(age);console.log(age);} func(22) //报错说没有这个函数因为上面覆盖了。 </script> <script> console.log(func); //f func(age) {var age;console.log(age);var age = 23;console.log(age);console.log(age);} function func(age) { var age; console.log(age); // f age() {} 这个来自于词法分析 var age = 23; function age() {} //不执行 console.log(age); // 23 } func(22) //这个就没有报错,因为上面没有所得到的词法分析没有被覆盖。 </script>
上面就是关于JavaScript的一些词法分析就是在执行代码的时候他会提前进行词法分析。上面是我个人学道德有些地方有可能说的不是很明白。没办法水平有限