关于Javascript程序员来讲,闭包总会让你以为既熟习又生疏,但是它关于开发人员来讲却非常重要,javascript里的很多设想形式中都用到了闭包,此处以函数作用域为例。
//示例代码
var a=1;
function foo(){
var b=2;
console.log(a);
function bar(){
var c=123;
console.log(b);
}
bar();
}
foo();
任何函数定义的时刻,都邑建立一个[[scope]]属性,这个对象对应的是一个对象的列表,列表中的对象仅能javascript内部接见,没法经由过程语法接见,用代码能够示意为:
1.函数定义时
在全局环境下定义了一个foo函数,此时foo函数的[[scope]]属性中只包含一个全局对象GO(global object)
//伪代码
//js代码默许进入全局实行环境,所以foo在初始时就被定义
foo.[[scope]]={
GO:{
this:window,
window:{...},
document:{...},
a:undefined //此处是预编译,所以a并没有赋值
....
}
}
//当进入foo实行环境时,bar函数才被定义
bar.[[scope]]={
AO(foo):{
this:window,
arguments:[],
b:undefined
},
GO:{
this:window,
window:{...},
document:{...},
a:1
}
}
2.函数被挪用时
实行环境
在函数实行时,会建立一个叫做实行环境/实行上下文(execution context)的内部对象
它定义了一个函数实行时的环境
函数每次实行时的实行环境举世无双
屡次挪用函数就屡次建立实行环境
而且函数实行终了后,实行环境就会被烧毁
实行环境有本身的作用域链,用于剖析标识符
所以当foo函数被挪用的时刻,会建立foo实行环境,每一个实行环境对应一个变量对象。首先会创一个它本身的运动对象【Activation Object】(这个对象中包含了this、参数(arguments)、局部变量(包含定名的参数)的定义,固然全局对象是没有arguments的)和一个变量对象的作用域链[[scope chain]],然后,把这个实行环境的[[scope]]按递次复制到[[scope chain]]里,末了把这个运动对象推入到[[scope chain]]的顶部。如许[[scope chain]]就是一个有序的栈,如许保了对实行环境有权接见的一切变量和对象的有序接见。
//foo函数被挪用时
foo.EC={ //foo的实行环境
AO:{ //foo的运动对象
this:window,
arguments:[],
b:undefined
},
[[scope chain]]:{
AO:AO, //推入作用域链顶部的运动对象
GO:{...} //经由过程复制foo.[[scope]]获得的全局对象
}
...
}
//函数的作用域链
foo.EC.[[scope chain]]={
AO:{
this:window,
arguments:[],
b:undefined
},
GO:{
this:window,
window:{...},
document:{...},
a:1
}
}
//当bar函数被挪用时
bar.EC={
AO:{
this:window,
arguments:[],
c:undefined
},
[[scope chain]]:{
AO:AO //推入作用域链顶部的运动对象
AO:{...} //foo运动对象
GO:{...} //全局运动对象
}
}
3.函数代码实行阶段
var b=2 实际上就是对作用域链AO对象中的b举行赋值,当实行console.log(a)时刻,碰到标识符a,就会依据标识符的称号在实行环境(Execution Context)的作用域链中举行搜刮。从作用域链的第一个对象(该函数的Activation Object对象)最先,假如没有找到,就搜刮作用域链中的下一个对象,云云来去,直到找到了标识符的定义。假如在搜刮完作用域中的末了一个对象,也就是全局对象(Global Object)今后也没有找到,则会抛出一个毛病,提醒undefined。
正式由于作用域链的这类关联,我们就不难明白,为何this和arguments不能经由过程作用域链向上搜刮,由于对this和arguments的搜刮在当前实行函数的运动对象就住手了。
以上是个人关于js作用域的明白, 若有毛病迎接议论,本文未触及with等转变作用域的行动
参考文章
http://www.cnblogs.com/pigtai…
http://blog.csdn.net/liujie19…
http://www.cnblogs.com/vadar/…
http://blog.csdn.net/q1056843…