对象
- 函数本身就是一个对象,具有自己的name、length等属性。
scope
- 独立的命名空间,外界无法访问空间内的变量。
scope && scope chain
- 函数被定义后,会生成scope。在其scope属性中存储scope chain,scope chain底端会存储外层函数的scope chain。此时函数的scope chain和外层函数的scope chain是相同的。
- 函数执行前,预编译时会生成AO,AO会占据scope chain的最顶端。程序执行时,会从最顶端依次往下寻找变量或函数声明,对其进行操作。
- 函数执行后,函数自身的AO将会销毁。意味着函数内部声明的变量、函数都会销毁。
function a(){
function b(){} // 由于b函数是在a函数的环境下,b函数被定义时,b函数的scope chain和a函数的scope chain是一样的。b chain: GO AO(a)
b(); // b函数预编译时,b函数的scope chain会从最底端存储。b chain: GO AO(a) AO(b)
// b函数执行后,b函数的scope chain回到b函数定义时的状态。b chain: GO AO(a)
}
a(); // a函数执行前一刻,开始预编译,生成自己的AO。a函数的scope chain会从最底端存储。a chain: GO AO(a)
// a函数执行后,a函数的scope chain回到a函数定义时的状态。a chain: GO
// a函数执行后,AO(a)被销毁,随之b函数的定义也被销毁。意味着b的scope不复存在。
-
函数a 和 函数b 运行期间各自的scope chain
question 1
- 外部函数为什么不能访问内部函数的成员变量?但内部函数可以访问外部?
- 原因:外部function的scope chain中不存在内部function的AO,但内部function的scope chain中存储了外部函数的AO。
闭包
- closure [ˈkloʊʒər] k lou 惹儿
function a(){
function b(){}
return b;
}
var c = a();
- 具体解释:当函数b被返回到a函数的外部时,并把函数b赋值给变量c,此时即会产生闭包现象。此时函数c的作用域链中会一直带着函数a的AO。
- 抽象解释:当内部函数被返回到外部并保存时,会产生闭包。闭包会导致作用域链不释放。过渡的闭包有可能导致内存泄漏。
- 作用域链指的是内部函数所在环境的作用域链。
- 直接返回function或把function放置到字面量对象或数组中再返回,同样会产生闭包。
function test(){
var x = 1;
var a = [
function(){console.log(x)},
function(){}
];
return a;
}
test()[0](); // 1
闭包延伸
function test(){
function test1(){
function test2(){
console.log(a);
console.log(b);
}
var b = 2;
return test2;
}
var a = 1;
return test1;
}
var test1 = test();
var test2 = test1();
test2(); // 1 2
// test [scope chain]----GO //test运行后
// test1 [scope chain]----GO AO(test) //test1运行后
// test2 [scope chain]----GO AO(test) AO(test1) //test1运行时
// test2 [scope chain]----GO AO(test) AO(test1) AO(test2) //test2运行时