前端预编译程序主要涉及JavaScript代码在运行前的编译过程,这个过程对于理解变量和函数的声明、作用域以及执行顺序至关重要。预编译可以分为全局预编译和局部预编译两个阶段。
全局预编译
创建全局对象GO(Global Object) :在页面加载完成时,JavaScript引擎会创建一个全局对象,通常在浏览器环境中这个对象就是`window`。加载脚本文件:
JavaScript代码通常被分割成多个脚本文件,这些文件会按照顺序加载。
预编译
找出所有的变量声明:
编译器会扫描代码中的所有变量声明,并将它们添加到全局对象中。如果变量名已经存在,则新的声明会覆盖旧的。
找出所有的函数声明:同样,编译器也会扫描代码中的所有函数声明,并将它们添加到全局对象中。如果函数名已经存在,则新的声明会覆盖旧的。
解析执行代码 :在预编译完成后,代码会按照顺序执行。
局部预编译
创建AO对象(Activation Object):
在函数执行前一刻,JavaScript引擎会创建一个激活对象,这个对象包含了函数执行所需的所有局部变量和参数。
找形参和变量声明:
编译器会扫描函数体内的所有变量声明,并将它们作为AO对象的属性,初始值为`undefined`。
将实参和形参统一:
在函数调用时,实参的值会被赋给AO对象中对应的形参。
找函数声明:
编译器会扫描函数体内的所有函数声明,并将它们作为AO对象的属性,值赋予函数体。
执行代码:
在预编译完成后,函数体内的代码会按照顺序执行。
示例
```javascript
function test(a) {
console.log(a); // undefined
var a = 1;
console.log(a); // 1
function a() {}
console.log(a); // [Function: a]
var b = function() {}
console.log(b); // [Function: b]
function d() {}
console.log(d); // [Function: d]
}
test(1);
```
在这个示例中,预编译的过程如下:
全局预编译
创建`window`对象。
变量声明`a`和`b`被添加到`window`对象中,初始值为`undefined`。
函数声明`a`、`b`和`d`被添加到`window`对象中。
局部预编译
创建`AO`对象。
形参`a`被赋值为`undefined`。
实参`1`被赋给`AO`对象中的`a`。
函数声明`a`、`b`和`d`被添加到`AO`对象中。
执行代码
`console.log(a)`输出`undefined`。
`var a = 1`执行,`AO.a`被赋值为`1`。
`console.log(a)`输出`1`。
函数声明`a`被赋给`AO.a`,`AO.a`变为函数。
`console.log(a)`输出`[Function: a]`。
变量声明`b`被赋值为`undefined`。
函数声明`b`被赋给`AO.b`,`AO.b`变为函数。
变量声明`d`被赋值为`undefined`。
函数声明`d`被赋给`AO.d`,`AO.d`变为函数。
通过了解前端预编译的过程,可以更好地理解JavaScript代码的执行机制和变量作用域的创建。这对于编写高效、可维护的代码非常有帮助。