作用域与作用域链
GO/VO/AO/EC及作用域和执行上下文
- GO:全局对象(Global Object)
let globalObject = {
Math:{},
String:{},
document:{},
...
window:this
}
- ECStack:Execution [ˌeksɪˈkjuːʃn] Context Stack 执行环境栈
- EC:Execution Context 执行环境(执行上下文)
- VO:Varibale Object 变量对象
- AO:Activation Object 活动对象 (函数的叫做AO,理解为VO的一个分支)
- Scope:作用域,创建的函数的时候就赋予的
- Scope Chain :作用域链
例如:
let x = 1;
function A(y){
let x = 2;
function B(z){
console.log(x+y+z);
}
return B;
}
let C = A(2);
C(3);
/*第一步:创建全局执行上下文,并将其压入ECStack中*/
ECStack = [
//=>全局执行上下文
EC(G) = {
//=>全局变量对象
VO(G):{
... //=>包含全局对象原有的属性
x = 1;
A = function(y){...};
A[[scope]] = VO(G); //=>创建函数的时候就确定了其作用域
}
}
];
/*第二步:执行函数A(2)*/
ECStack = [
//=>A的执行上下文
EC(A) = {
//=>链表初始化为:AO(A)->VO(G)
[scope]:VO(G)
scopeChain:<AO(A),A[[scope]]>
//=>创建函数A的活动对象
AO(A) : {
arguments:[0:2],
y:2,
x:2,
B:function(z){...},
B[[scope]] = AO(A);
this:window;
}
},
//=>全局执行上下文
EC(G) = {
//=>全局变量对象
VO(G):{
... //=>包含全局对象原有的属性
x = 1;
A = function(y){...};
A[[scope]] = VO(G); //=>创建函数的时候就确定了其作用域
}
}
];
/*第三步:执行B/C函数 C(3)*/
ECStack = [
//=>B的执行上下文
EC(B){
[scope]:AO(A)
scopeChain:<AO(B),AO(A),B[[scope]]
//=>创建函数B的活动对象
AO(B):{
arguments:[0:3],
z:3,
this:window;
}
},
//=>A的执行上下文
EC(A) = {
//=>链表初始化为:AO(A)->VO(G)
[scope]:VO(G)
scopeChain:<AO(A),A[[scope]]>
//=>创建函数A的活动对象
AO(A) : {
arguments:[0:2],
y:2,
x:2,
B:function(z){...},
B[[scope]] = AO(A);
this:window;
}
},
//=>全局执行上下文
EC(G) = {
//=>全局变量对象
VO(G):{
... //=>包含全局对象原有的属性
x = 1;
A = function(y){...};
A[[scope]] = VO(G); //=>创建函数的时候就确定了其作用域
}
}
];
深入学习1
let x = 5;
function fn(x) {
return function(y) {
console.log(y + (++x));
}
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
//结果是:14 18 18 5
深入学习2
let x = 5;
function fn() {
return function(y) {
console.log(y + (++x));
}
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
深入学习3
let a=0,
b=0;
function A(a){
A=function(b){
alert(a+b++);
};
alert(a++);
}
A(1);
A(2);
注意;先赋值 自身再累加
极其深入学习4
var x = 3,
obj = {x: 5};
obj.fn = (function () {
this.x *= ++x;
return function (y) {
this.x *= (++x)+y;
console.log(x);
}
})();
var fn = obj.fn;
obj.fn(6);
fn(4);
console.log(obj.x, x);