函数的声明方式
var fun = function(){
console.log(111);
}
function fun2(){
console.log(222);
}
函数的工作原理
作用:代码的复用 可以实现一个独立的小功能
编译器:负责解析代码
内存:负责储存代码运行时产生的数据
为什么要进行代码预编译
预编译的好处:可以让函数在任意位置被调用
什么是预编译机制:就是JS代码执行前,会把函数或者变量声明提升到所在作用域的最顶端
js代码的执行过程
(1)语法检测
函数执行前 先进行扫描一遍 看看有没有语法错误,有就报错,没有就进行预编译
(2)预编译
GO 生成过程:
GO对象(Global Object)全局变量
- 生成一个GO对象,封装的就是作用域 GO = {}
- 分析变量声明(var) 就是声明的变量名作为GO对象的属性,值为undefined
- 分析函数声明 函数名作为GO对象的属性名,属性值为函数体,如果遇到同名函数 直接覆盖 当遇到有变量和函数同名的时候,变量提升的优先级大于函数提升的优先级,(先进行变量提升,在进行函数提升)
- 当走到某一行的时候,当变量产生一次赋值,那么GO对象发生变化
(3)逐行执行
var a;
function fun(){};
function abc(){};
function a(){};
console.log(a);
var a = 12;
console.log(a);
/*
1.声明一个GO对象
GO = {}
2.分析变量声明(var)
GO = {a : undefined}
3.分析函数声明(function)
GO = {
a : undefined
fun : function fun(){};
abc : function abc(){};
}
*/
生成AO的步骤
在函数被调用执行前的一个瞬间,生成一个AO对象(Active Object)
- 在函数执行前的一瞬间,生成一个AO对象 AO = {}
- 分析参数,形参作为AO对象的属性名,实参作为属性值
- 分析变量声明 变量作为属性名,值为undefined,如果遇到同名的 不发生任何改变
- 分析函数声明 函数名作为属性名 函数体为属性值,如果遇到同名的 直接覆盖
function fn(a) {
console.log(a);//函数体
var a = 123;
console.log(a); //123
function a() { };
console.log(a); //123
var b = function () { }
console.log(b); //函数体
function c() { };
console.log(c);
}
fn(1);
分析步骤:
/*
1.生成AO对象 fn.AO = {}
2.分析参数 fn.AO = {a:1}
3.分析变量声明
fn.AO = {
a:1,
b:undefined
}
4.分析函数声明
fn.AO = {
a:function a(){},
b:undefined,
c:function c(){}
}
*/
运行结果:
// ƒ a() { }
// 123
// 123
// ƒ () { }
// ƒ c() { }
例题分析
例题:
function test() {
console.log(b);
if (a) {
var b = 100;
c = 234;
console.log(c);
}
var a;
test();
a = 10;
test();
console.log(c);
分析过程
/*
1.生成GO对象 GO = {}
2.分析变量 GO = {a :undefined, c:undefined}
3.函数声明
GO = {
a :undefined ,
test: function test() {
console.log(b);
if (a) {
var b = 100;
}
c = 234;
console.log(c);
}
}
4.变量重新赋值
GO = {a:10}
1.生成一个AO对象 AO = {}
2.分析参数 略过
3.分析变量声明 AO = { b : undefined }
4.分析函数声明 略过
*/