代码
function foo(){
var name="foo"
var age=18
function bar(){
console.log(name)
console.log(age)
}
return bar
}
var fn=foo()
fn()
分析
//第11行代码执行 , 生成AO对象。
//接下来执行函数中的代码:
//函数执行上下文会被销毁;但是AO1对象不会被销毁。
//0xb00对象不会被销毁 , 因为有fn指着它(全局GO中的变量)。
//0xb00中又有引用指向了AO1对象。
//从根对象出发 , 如果没有某个引用指着X对象了 ,那么X对象就会被销毁。
//fn( ) 要开始执行了。创建Fn的函数执行上下文。
//bar函数在当前的AO2中没有找到name , 于是就又跑到parentScope中寻找 , 找到了。
//fn()执行完毕 , 函数上下文弹栈。
//本来bar的上下文对象是指着0x300的,但是弹走了,就没有东西指向0x300了~
//归根结底 , 是因为父级作用域parentScope指着AO对象 , 所以AO对象没有被销毁。
//bar函数对象不会被销毁 , 所以后面的代码能够直接使用这个bar函数 ;
//——也正是因为bar函数没有被销毁 , 所以bar函数中的parentScope对象一直指着AO1对象,AO1对象也不会被销毁。
//但又如果说:bar函数只执行一次 , 那么保存AO1对象(0x200)和bar函数对象(0xb00)都是没有意义的。
这样就形成了闭包 , 闭包在一定程度上是有内存泄漏的,我只使用一次bar函数 , 但是bar函数对象和AO1对象却一直存在着,但是这种内存泄漏在一定程度上又取决于你是否要继续使用,这种内存泄漏在你不使用的情况下 , 应该被销毁掉!——fn=null.
//当我们执行代码 fn=null; 的时候上图就会变成下图的样子:
//从GO出发 , 右侧的两个对象0x200和0xb00虽然能够互相引用,但是脱离了GO的管控 ,自然就要被销毁了~
此时如果执行下面所述的代码 , 那么foo对象也会被销毁!
foo=null;