AO
- 创建AO(Activation Object)对象,又叫执行期上下文;
- 寻找形参和变量声明作为AO的属性名,并赋值为undefined;
- 传入实参的值;
- 在函数体内寻找函数声明,放入作为AO的属性,并赋值为其函数体。
GO
- 创建GO(Global Object)对象;
- 寻找变量声明作为GO的属性名,并赋值为undefined;
- 寻找函数声明,放入作为GO的属性,并赋值为其函数体。
相关的代码输出题目1 [AO]
function test(a, b) {
console.log(a); // function a(){return 'a'}
var c = 123;
console.log(c); // 123
function a() {
return 'a';
}
console.log(b); // 2
var b = function c() {
return 'b';
}
console.log(b); // function a(){return 'b'}
}
test(1, 2);
// 创建一个AO对象(activation object),AO{}
// 寻找形式参数和变量声明作为AO的属性名,并赋值为undefined
AO {
a: undefined,
b: undefined,
c: undefined
}
// 传入实参的值
AO {
a: 1,
b: 2,
c: undefined
}
// 在函数体内寻找函数声明,放入作为AO的属性,并赋值为其函数体
AO {
a: function(){return 'a'},
b: 2,
c: undefined
}
//执行过程
a输出AO中的结果
c被赋值为123
b未被重新赋值,为AO中的值
b被重新复制为函数
相关的代码输出题目2
function Foo() {
getName = function() {
console.log(1);
}
return this;
}
Foo.getName = function () {
console.log(2);
}
Foo.prototype.getName = function () {
console.log(3);
}
// 给全局变量赋值一个匿名函数
var getName = function() {
console.log(4);
}
// 函数声明
function getName() {
console.log(5);
}
// 1. 调用Foo函数上的静态方法
Foo.getName(); // 2
/*
* 2. 直接调用getName函数
* GO{
* getName: undefined => 初始化时,var的变量提升
* getName: function(){console.log(5)} => function有变量提升
* getName: function(){console.log(4)} => 变量的赋值行为
* }
* */
getName(); // 4
/*
* 3. 直接调用构造函数Foo, this指向window
* 函数内部的getName没有使用var,let,const声明,则该变量为全局变量,且发生了重新赋值行为
* getName: function(){console.log(1)}
* */
Foo().getName() // 1
// 4. window.getName() => 1 (GO内getName()输出1)
getName() // 1
// 5. new (Foo.getName()) => 将Foo.getName()作为构造函数
// 作为普通函数 this指向调用者,作为构造函数 this指向实例对象
// 输出2 是在执行构造函数过程中的一个输出
new Foo.getName() // 2
// 6. 先执行new Foo()创建实例对象,调用实例对象身上的getName方法 => 自身实例对象没有,去原型链上寻找
new Foo().getName() // 3
// 7. 综合上边的5,6 => 把6作为构造函数
new new Foo().getName() // 3