博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js闭包,垃圾回收,内存泄漏
阅读量:7153 次
发布时间:2019-06-29

本文共 2381 字,大约阅读时间需要 7 分钟。

1.闭包的概念

闭包:指有权访问另一个函数作用域中的变量的函数。

闭包的本质是将函数内部和函数外部连接起来的一座桥梁。

2.如何创建闭包

例1:

function outer(){    var a=1;    function inner(){        a++;      alert(a);    }    return inner;}var f1=outer();//创建了一个闭包,f1能访问outer函数中的变量f1();//弹出2.

这段代码的特点在于:

1.函数inner嵌套在函数outer内部
2.函数outer返回函数inner,并将值赋给了f1
例2:

// 实现累加:方式1var a = 0;var add = function(){    a++;    console.log(a)}add();add();//方式2 :闭包var add = (function(){    var  a = 0;    return function(){        a++;        console.log(a);    }})();console.log(a); //undefinedadd();add();//方式2的优点:减少全局变量,将变量私有化

3.闭包与变量的关系

闭包只能取得包含函数中任何变量的最后一个值。

例:

function f1() {    var res = new Array();    for(var i=0;i<10;i++){        res[i] = function() {            alert(i);        };    }    return res;}var f2 = f1();var f2 = f1();f2[0]();//alert 10//并不会返回一次弹出0-9的函数数组,而是弹出10个10的函数数组,因为res中每个函数的作用域中都保存着f1()的活动对象,引用的是同一个变量i,当f1()返回后i的值为10

解决方法:

function f1() {    var res = new Array();    for(var i=0;i<10;i++){        res[i] = (function(num) {            return function (){                alert(num);            }        })(i);//函数参数按值传递    }    return res;}var f2 = f1();var f2 = f1();f2[0]();//alert 0

4.内存泄露及解决方案

垃圾回收机制

说到内存管理,自然离不开JS中的垃圾回收机制,有两种策略来实现垃圾回收:标记清除 和 引用计数;

标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量的标记和被环境中的变量引用的变量的标记,此后,如果变量再被标记则表示此变量准备被删除。 2008年为止,IE,Firefox,opera,chrome,Safari的javascript都用使用了该方式;

引用计数:跟踪记录每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这个值的引用次数就是1,如果这个值再被赋值给另一个变量,则引用次数加1。相反,如果一个变量脱离了该值的引用,则该值引用次数减1,当次数为0时,就会等待垃圾收集器的回收。

这个方式存在一个比较大的问题就是循环引用,就是说A对象包含一个指向B的指针,对象B也包含一个指向A的引用。 这就可能造成大量内存得不到回收(内存泄露),因为它们的引用次数永远不可能是 0 。早期的IE版本里(ie4-ie6)采用是计数的垃圾回收机制,闭包导致内存泄露的一个原因就是这个算法的一个缺陷。

我们知道,IE中有一部分对象并不是原生额javascript对象,例如,BOM和DOM中的对象就是以COM对象的形式实现的,而COM对象的垃圾回收机制采用的就是引用计数。因此,虽然IE的javascript引擎采用的是标记清除策略,但是访问COM对象依然是基于引用计数的,因此只要在IE中设计COM对象就会存在循环引用的问题!

例子:

window.onload = function(){    var ele = document.getElementById("id");    ele.onclick = function(){        alert(ele.id);    }}

这段代码为什么会造成内存泄露?

ele.onclick = function(){        alert(ele.id);    }

执行这段代码的时候,将匿名函数对象赋值给ele的onclick属性;然后匿名函数内部又引用了ele对象,存在循环引用,所以不能被回收。

解决方法:

window.onload = function(){    var ele = document.getElementById("id");    var id = ele.id; //解除循环引用    ele.onclick = function(){        alert(id);     }    ele = null; // 将闭包引用的外部函数中活动对象清除}

5.总结闭包的优缺点

优点:

  • 当需要一个变量常驻内存时,闭包可以实现一个变量常驻内存 (如果多了就占用内存了)

  • 避免全局变量的污染

  • 私有化变量

缺点:

  • 因为闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存

  • 引起内存泄露

转载地址:http://zurgl.baihongyu.com/

你可能感兴趣的文章
SEO系列一:SEO是什么?SEO有什么意义?
查看>>
快递小哥逆袭自传:用了6年时间做到了IT部门主管
查看>>
程序coredump原因
查看>>
button只能点击一次的限制
查看>>
回调函数的理解
查看>>
STM32F767IGT6上电多次重启问题查找与解决
查看>>
hadoop
查看>>
Getting Started in OS Development开发自己的操作系统
查看>>
HEX文件格式
查看>>
JVM调优之:内存模型
查看>>
1.3列出文件属性 ls
查看>>
easyui filebox文件类型判断
查看>>
java.lang.IllegalArgumentException: java.net.UnknownHostException: hadoop.baizhiedu.com
查看>>
DIY Hadoop大数据五大注意点
查看>>
Jenkins安装
查看>>
安装配置Windbg
查看>>
Ubuntu系统安装nginx
查看>>
动态网页爬取
查看>>
php-nginx超时时间过短导致的post失败
查看>>
阿里面试题BIO和NIO数量问题附答案和代码
查看>>