三个闭包实例理解闭包对内存的影响

在试图弄清这个问题以前,先要理解栈内存、堆内存和预处理javascript

占用内存,不会销毁的闭包实例

例1:

var num = 12;
function fn() {
    var num = 100;
    return function () {
        console.log(num);
    }
}
var f = fn();
f();

例1的图示java

未被占用的堆内存才会被销毁git

因此,正如图中椭圆形关键点中说明的那样,堆内存xxxfff111被返回给了全局变量f,而全局变量只有在窗口关闭的时候才会销毁,所以堆内存xxxfff111将一直被占用而不会销毁,定义它的局部做用域A也不会被销毁。github

例2

var oDiv = document.getElementById("div1");
~function() {
    oDiv.onclick = function() {

    }
}();

这段代码的特色是:私有做用域给DOM元素的事件绑定一个方法。闭包

例2的图示:函数

正如图中椭圆形关键点所说,标签对象的属性里面会自带一个onclick的属性,未被赋值时其值为null。那么,在自执行函数执行的时候,其建立的做用域所占用的堆内存xxxfff111一样也会被全局的堆内存xxxfff000占用(这里要注意,是堆内存占用堆内存),因此堆内存xxxfff111和栈内存A都不会被销毁。spa

不占用内存,当即销毁的实例

只须要将例1稍做修改。设计

例3:

function fn(){
    var num = 100;
    return function(){
        console.log(num);
    }
}
fn();    //主要修改在这里

例3的图示code

因为在函数fn中,xxxfff111是被return的,因此栈内存A的预解释不会处理xxxfff111,它只在fn函数执行的时候才会生成,而函数fn的栈内存A每次被执行以后都会被销毁。对象

暂时占用内存,延时销毁的闭包实例

将例3稍做修改,就变成了延时销毁的闭包实例。

例4:

function fn(){
  var num = 100;
  return function(){

  }
}
fn()();    //这里到底发生了什么?实际上是执行了一次fn以后,把返回的子函数有执行了一次,因此在子函数执行的时候,栈内存fn()是不能销毁的,可是子函数执行完毕后由于没有被占用,因此最终fn()仍是会被销毁的。

例4的图示:

正如图中椭圆形关键点处所说,fn()()的意思是在执行完fn()以后再把返回的值函数执行一遍。所以在子函数执行的时候,堆内存xxxfff111被占用了,相应的栈内存A也将保留。

可堆内存xxxfff111中保存的子函数在执行完成以后仍是会被销毁,接着堆内存xxxfff111就做为未被占用的堆内存而被销毁,最终栈内存A也会被销毁。

因此,栈内存在执行完以后会被保留一段时间,这段时间等于其子函数执行的时间。

参考资料:

JavaScript高级程序设计(第三版)。

我在github
https://github.com/zhuanyongx...

相关文章
相关标签/搜索