AO生成过程四部曲:
1.先局部(在函数作用域内)创建AO对象.
2.将函数的形参 、变量声明中的形参名和变量名作为AO的属性名,值为undefined.
3.将实参值赋予形参.
4.在函数体里找函数声明,将函数名作为AO的属性名,值为函数体.
在执行过程中AO的属性值会按函数内部执行顺序从上而下的进行覆盖,也就是同名不同值的会按先后顺序被覆盖
例一:
<script>
function fn() {
console.log(a);
var a = 1;
console.log(a);
}
fn();
</script>
求上面fn函数的打印结果;我们根据四部曲来逐步分析。
AO {
a:undefined
}
function fn() {
console.log(a); ==> 此时AO里的a的属性值为undefined ,打印a的值即为undefined
a = 1; ==> 此时AO里的a的属性值被重新赋值变为1console.log(a); ==> 此时再次打印a的值是1
}
fn();
来看下运行结果:
例二:
function test(a, b) {
document.write(a);/*1*/
c = 0;/**/
var c;
a = 3; b = 2;
document.write(b);/*2*/
function b() { }
function d() { }
document.write(b);/*2*/
}
test(1);
AO {
a: 1,
c :undefined,
b:function b(){ },
d:function d(){ },
}
function test(a, b) {
document.write(a);==> AO里的a为1,输出a为1 /*1*/
c = 0; ==> 此时AO里的c被重新赋值变为0
var c; ==> 变量c已被提升,不用分析
a = 3; b = 2; ==> 此时AO里的a和b被重新赋值变为3和2
document.write(b); ==> 此时打印b为2 /*2*/
function b() { } ==>函数b已提升不用分析
function d() { } ==>函数d已提升不用分析
document.write(b); 此时打印b为2 /*2*/
}
来看下打印结果:
例三
function test(a, b) {
console.log(a); /* function a() { }*/
console.log(b); /*ud*/
var b = 234;
console.log(b); /*234*/
a = 123;
console.log(a);/*123*/
function a() { }
var a;
b = 234;
var b = function () { }
console.log(a);/*123*/
console.log(b); /*function () { }*/
}
test(1);
AO {
a:function a() { },
b:undefined
}
function test(a, b) {
console.log(a); ==> 初始时AO里的a为function a() { },打印即为函数体function a() { } console.log(b); ==> 同理b为undefined,打印即为undefined
var b = 234; ==> 此时相当于b被提升,b被重新赋值变为234
console.log(b); ==>此时打印b即为234
a = 123; ==>a 被重新赋值变为123
console.log(a); ==> 此时打印a即为123
function a() { } ==>函数a已提升不用分析
var a; ==>变量a已提升不用分析
b = 234; ==>b重新赋值变为234
var b = function () { } ==> b被重新赋值变为function () {}
console.log(a); ==> 打印a即为123
console.log(b); ==> 打印a即为function () {}
}
test(1);
打印结果:
小结:我们可以看出js引擎在生成AO后开始一行行读取函数内部代码,过程中若出现函数声明的名称和变量名名称相同的情况时,对应的值会根据先后顺序进行层叠覆。所以在分析过程中我们要一层层的对变量函数进行分析。