Js内存回收
Javascript的世界中,隐藏了很多内存陷阱,不能得到合理释放的内存会埋下各种隐患,本文旨在以实用角度去解读Js涉及到的内存,且看勇士如何斗恶龙~
本文可以看做是之前那篇勇士斗恶龙之没那么复杂的Js闭包的后续篇,在思考闭包中内存的问题时,有了写此文的冲动.
学以致用,从实用的角度出发我们最需要关注的就是内存回收用什么用处?我们日常工作中好像不需要我们自己去处理Javascript中的内存,它会自动回
收的.如果你问Javascript内存回收,一定会有TX鄙视的告诉你,这个会自动回收,不需要我们自己处理.
Javascript中的内存,真的不需要我们关注吗???
通常这种自问自答的结果,就是会给出一个与问题相反的答案,也就是当然需要!Javascript虽然会自动处理内存,但不是完美的,它存在一定的缺陷.另一方面,我们不能因为无知而无畏,因为可能很多莫名其妙的问题就是这样出现的.
内存-那些我们忽略的就是我们要拯救的
在平时的编码中我们无时无刻不在执行这样的一个过程,分配内存 -> 使用内存 ->
回收内存.如此反复的过程在不断持续着,每一个数字,字符串,对象,数组,方法都占用着计算机的内存.前端编程因为你的Js代码大部分运行在客户端浏览
器,所以虽然你没有占用服务器的内存,可是你占用了使用者的内存.即使在硬件配置越来越高的今天,也不能完全保证我们产品的使用者不是古老的机器,况且你
也应该考虑到移动手机的性能.也不是说每一台机器都配有4G以上的内存供你挥霍,我一直认为好的程序员对待内存要保持一个吝啬的心态.
Javascript在分配内存这一过程中,会根据不同的数据类型进行分配.像基本数据类型会分配在栈内存,引用数据类型分配在堆内存中.引用对于理解内存是一个很重要的概念,我最早对引用的理解来自于C里面的指针,最好找资料仔细了解一下.
|
1
2
3
4
|
var obj = {name:"benze"};var car = obj;//这里car就是指向了obj所创建的那个对象所在的内存空间,也就是说此时obj和car都指向了同一块内存.//在内存管理的环境中,如果一个对象有权限去访问另一个对象,就叫做一个对象引用另一个对象 |

我们平时在使用定义变量,函数或者对象的时候,都在进行各种的内存分配,但是通常不需要写代码去回收,因为我们知道它是自动回收的.这里我得强调,自动不代表我们就不要考虑内存回收了.
使用内存-也就是那些读读写写
关于内存的使用,我的理解就是对于已经开辟好内存空间的那些值,进行一些读写操作.这一过程中可能还有对象引用的改变等等,因为这个不是本文重点,不加以赘述.
内存回收 === 屠龙之术?
话说古时候有人散尽家财学的屠龙之术,技成之后却发现无龙可屠.那Javascript既然有着自动回收的内存管理,我们学习内存回收岂不也是一样,反正
它能正常回收就行呗,我们管它是怎么回收的呢.但是问题是我之前提到过,Javascript的垃圾回收机制有一定的局限性和缺陷,有一些情况会使得内存
得不到释放而持续增加,这时候我们就需要人为的处理它.
引用计数的回收机制
上文提到过引用的概念,Javascript的内存回收的算法主要就依赖于引用,当代码生成一个新的内存驻留项时(如一个对象),系统就会为它开辟一块内
存空间.因为这个对象可能会被传递给其他函数,或者对象.所以可能很多代码都会指向这个对象的内存空间.javascript的垃圾回收器跟踪这些指向,
当最后一个指向都被断开废弃的时候,这个对象所占用的空间就会被释放.
这是一种比较简单并且清晰的算法,看上去感觉没什么问题,但是如果出现这种情况呢?
|
1
2
3
4
|
var a = {name:'a'};var b = {name:'b'};a.bname = bb.aname = a; |
代码看着很别扭是吧,但是如果真有这种情况呢,彼此引用.这样的情况,javascript的的回收就对a和b没有办法了.对于这种循环引用,实在是各类垃圾自动回收的缺陷.
真实情况的内存无法回收
也许上面说的那种情况对于你来说永远不可能发生,平时注意点也许就避开了,但是总有些情况,也许你写了很久自己都没发现.在稍微旧一点版本的IE下,Javascript的对象是通过标记清除的,BOM和DOM对象却是通过引用计数,涉及到DOM或者BOM的时候就容易出现循环引用.上代码瞅瞅:
|
1
2
3
4
5
6
|
<span></span>$(document).ready(function(){ var div = document.getElementById("mydiv"); div.onclick = function(){ console.log("div"); }});<span></span> |
当指定的单击事件处理程序时,创建了一个在其封闭的环境中包含div变量的闭包环境.而div也包含一个指向闭包的引用(onclick属性自身),这就导致了内存都不能得到释放.当然解决方法很简单:
|
1
2
3
4
5
6
7
|
$(document).ready(function(){ var div = document.getElementById("mydiv"); div.onclick = saydiv;});function saydiv(){ console.log("div");} |
此时因为saydiv函数不在包含div的引用,所以没有形成循环,内存可以得到释放.
可能很多人都知道将一个对象置为null,那么它的内存就会回收.这是因为变量的指向了一个null,那么它原来指向的那块内存空间就会因为没有被指向,或者说没有被引用,而被垃圾回收掉.
标记清除-手动内存回收竟然还是屠龙之术?
从2012年起现代浏览器中,对于Javascript垃圾回收的机制进行了更新.不再使用引用计数的算法,而是改为使用标记清除的方式.比如定义一个变
量,那么当它进入执行环境时,会被垃圾回收器标记为"进入环境",当其离开环境比如函数执行完毕的时候,标记为"离开环境".垃圾回收机器就会在这些"离
开环境"的变量中挑选出来需要回收掉的变量用于释放内存.
这存在一个挑选标准,它不会再去计
算引用的数量.而是从全局对象(根节点)开始寻找,找到所有可获得的对象和所有不可获得的对象.也就是它从之前判断"对象是否被需要"变成"对象是否可以
获得".这么理解,零引用的对象总是不可获得的,但是不可能获得的对象不一定零引用.
如此除了在比较低版本的IE的情况下,Javascript的自动回收机制就足以应付大多数情况了.在高级一点的IE中对于内存回收也有很大的进步,所以还是推荐大多数情况下不要手工的回收垃圾.
尾笔
本来不打算写这段尾笔,不过为了避免本文有虎头蛇尾的嫌疑,还是要补充说明一下.首先是大部分现代浏览器都已经对内存做了很好的处理,所以大多数情况下不
需要我们手工执行.其次本文的目的在于归纳总结,而不是非要写出什么特殊东东.最后写此文也是为了给我自己和看过的人提个醒:
- 不要因为是Web的前端就忽视了内存这个因素,更别以为所有人的电脑都会配有2G乃至4G的内存.
- 本文最大的作用是指出一些可能存在的陷阱,不是告诉大家掉进去怎么办,而是怎样避免掉进去.
- 循环引用,闭包,DOM操作,这3点是我认为最容易造成内存问题.
- 别因为你从来没遇到Javascript内存的问题而忽视乃至忘却它,优秀的程序员应该吝啬计算机的资源.
Js内存回收的更多相关文章
- JavaScript闭包(内存泄漏、溢出以及内存回收),超直白解析
1 引言 变量作用域 首先我们先铺垫一个知识点--变量作用域: 变量根据作用域的不同分为两种:全局变量和局部变量. 函数内部可以使用全局变量. 函数外部不可以使用局部变量. 当函数执行完毕,本作用域内 ...
- js 作用域链&内存回收&变量&闭包
闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等 一.作用域链:函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在 ...
- js垃圾回收及内存泄漏
js垃圾回收 js能够自动回收申请却未使用的内存,由于每次清除需要的性能较大,不是时时在刷新,而是每隔一段时间才进行一次. 回收的两种方式 标记清除(常用) 在内存中先标记变量,然后清除那些那些进入环 ...
- js垃圾回收与内存泄漏
js垃圾回收机制 概念: javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中的使用的内存.而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况 ...
- js垃圾回收和内存泄漏
js垃圾回收和内存泄漏 js垃圾回收 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. 1.标记清除(常用) 工作原理:是当变量进入环境时,将这个变量标记为"进入环境& ...
- javascript js 内存泄露
JavaScript 内存泄露 1.什么是闭包.以及闭包所涉及的作用域链这里就不说了. 2.JavaScript垃圾回收机制 JavaScript不需要手动地释放内存,它使用一种自动垃圾回收机制(ga ...
- Chrome JS内存泄漏排查方法(Chrome Profiles)
原文网址:http://blog.csdn.net/kaitiren/article/details/19974269 JS内存泄漏排查方法(Chrome Profiles) Google Ch ...
- JS内存泄漏 和Chrome 内存分析工具简介(摘)
原文地址:http://web.jobbole.com/88463/ JavaScript 中 4 种常见的内存泄露陷阱 原文:Sebastián Peyrott 译文:伯乐在线专栏作者 - AR ...
- Js内存泄露问题总结
最近接受了一个Js职位的面试,问了很多Js的高级特性,才发现长时间使用已知的特性进行开发而忽略了对这门语言循序渐进的理解,包括Java我想也是一样,偶尔在Sun官方看到JDK6.0列举出来的new f ...
随机推荐
- jquery 监听input输入值事件
<html> <head> <title></title> <script type="text/javascript" sr ...
- IOS对.Net返回的Base64string解析问题
1.c#生成Base64字符串的代码 string body = "{\"title\":\"上次CVR卡其\",\"url\": ...
- Hyper-V初涉_虚拟磁盘链错误的解决方案
当Hyper-V管理器对虚拟机创建了快照,在Hyper-V虚拟机设置中会看到如下图提示.简单的说,就是创建了快照的虚拟机将不能继续进行编辑. 如果,在对虚拟机的主虚拟磁盘进行了编辑,哪怕仅仅是在Win ...
- HTTP方法:GET对比POST
http://blog.csdn.net/zhenyu5211314/article/details/17067817
- NoSQL 精粹
1.2 阻抗失谐:关系型数据库过于简单和标准的表达方式(表+行或者说关系relation+元组tuple)不能很好的映射到应用(如表达嵌套:和其它表达方式如XML).解决办法:对象-关系映射框架,但查 ...
- 【ContextMenu】DataContext不自动更新
参考资料 http://www.orcode.com/article/Presentation_20147076.html 问题现象 通过绑定集合至ContextMenu的ItemsSour ...
- 如何查看Android的Keystore文件的SHA1值
像使用百度地图api时候,一般需要获取keystore的SHA1值,这里就手把手教大家如何查看Android的keystore文件中的SHA1值. 第一步: 打开cmd,切换到keystore所在的文 ...
- 避开WebForm天坑,拥抱ASP.Net MVC吧
有鹏友在如鹏网的QQ群中提了一个问题: 请问,在ASP.Net中如何隐藏一个MenuItem,我想根据不同的权限,对功能菜单进行隐藏,用style不行. 如果要仅仅解答这个问题,很好解答,答案很简单: ...
- 必须知道的SQL编写技巧,多条件查询不拼字符串的写法
在做项目中,我们经常遇到复杂的查询方法,要根据用户的输入,判断某个参数是否合法,合法的话才能当作过滤条件,我们通常的做法是把查询SQL赋值给一个字符串变量,然后根据判断条件动态的拼接where条件进行 ...
- [php入门] 3、WAMP中的集成MySQL相关基础操作
前言:本文以小白视角了解WAMP集成开发环境中的MYSQL,涉及的面广而浅,算是导读性质. 1.启动运行熟悉WAMP中的MySQL 先有库.再有表.数据最终以记录的形式插入表中.其中对数据进行操作使用 ...