深入理解scope
一. 简单的例子
var a = 1;
function fn(a){
console.log(a)
var a = 2;
}
fn(3)
显而易见,结果是3。
var a = 1;
function fn(a){
console.log(a)
a = 2;
}
a = 10;
fn()
答案是undefined,如果答案不对的话,你的函数预编译需要好好学一下。预编译
二. 执行的过程
function a(){
function b(){
function c(){
}
c()
}
b()
}
a()
1,调用a()函数之前,会有一个初始化的时候。这时候调用一个[[scope]],里面有GO对象。
[[scope]]:每个javascript函数都是一个对象。对象中有些属性我们可以访问,有些不可以访问,他们只供javascript引擎存取。
[[scope]]就是其中一个,[[]]指的就是我们所说的作用域,其中存储了运行期上下文集合。
作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式结构,就叫做作用域链[[scope chain]]
a().[[scope]]={
这里是当前作用域;
[[scope chain]]={
这里是作用域链
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}
执行期时,在执行的前一刻,会有一个执行期上下文。创建完成后,把执行期上下文放到作用域链[[scope chain]]上面,他们共同组成的新对象叫活跃对象。
执行期上下文:当函数执行前一刻。会创建一个称为执行期上下文的内部对象(AO),每个执行期上下文都是独一无二的,当函数 执行完后,就自动销毁。
a().[[scope]]={
[[scope chain]]={
AO:{
this:window,
argument:[],
b:function
},
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}
2.在继续调用b函数,b函数也会初始化,也调用[[scope]]。
b().[[scope]]={
[[scope chain]]={
AO:{
this:window,
argument:[],
c:function
},
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}
在执行前创建b函数的执行期上下文,放到作用域链上面,放上去后将作用域链的活跃对象提升到[[scope]]
b().[[scope]]={
[[scope chain]]={
AO:{
this:window,
argument:[],
c:function
},
AO:{
this:window,
argument:[],
b:function
},
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}
3.在继续调用c函数,c函数也会初始化,也调用[[scope]]。
c().[[scope]]={
[[scope chain]]={
AO:{
this:window,
argument:[],
c:function
},
AO:{
this:window,
argument:[],
b:function
},
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}
在执行前创建b函数的执行期上下文,放到作用域链上面,放上去后将作用域链的活跃对象提升到[[scope]]
b().[[scope]]={
[[scope chain]]={
AO:{
this:window,
argument:[]
}
AO:{
this:window,
argument:[],
c:function
},
AO:{
this:window,
argument:[],
b:function
},
GO:{
this:window,
window:object,
document:object,
a:function
}
}
}