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 ...
随机推荐
- u3d avatar部件的理解
u3d中带动画的fbx文件导入的时候,就会显示一个avatar组件,这个到底干嘛的一直没能很好的理解,翻看网上的介绍,基本都是告诉你,设置humanoid类型动画时,拖拉过去之类,但是这玩意到底存储了 ...
- Unity3d中Update()方法的替身
在网上看到一些资料说Unity3d的Update方法是如何如何不好,影响性能.作为一个菜鸟,之前我还觉得挺好用的,完全没用什么影响性能的问题存在.现在发现确实有很大的问题,我习惯把一大堆检测判断放在U ...
- jar包合并
多个jar包合并: 1.首先将所以要合并的jar包解压到同一目录中.jar xvf xxx.jar 2.用jar命令将所有.class, .aidl文件打包. jar cvf output.jar ...
- CSS 禁止浏览器滚动条的方法(转)
1.完全隐藏 在<boby>里加入scroll="no",可隐藏滚动条: <boby scroll="no"> 这个我用的时候完全没效果 ...
- Linux常用目录
- libnode 0.4.0 发布,C++ 语言版的 Node.js
libnode 0.4.0 支持 Windows ,提升了性能,libuv 更新到 0.10.17 版本,libj 更新到 0.8.2 版本. libnode 是 C++ 语言版的 Node.js,和 ...
- 人人都是 DBA(X)资源信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- AMD加载器实现笔记(四)
继续这一系列的内容,到目前为止除了AMD规范中config的map.config参数外,我们已经全部支持其他属性了.这一篇文章中,我们来为增加对map的支持.同样问题,想要增加map的支持首先要知道m ...
- JavaScript函数柯里化
函数式 JavaScript是以函数为一等公民的函数式语言.函数在JavaScript中也是一个对象(继承制Function),函数也可以作为参数传递成函数变量.最近几年函数式也因为其无副作用的特性. ...
- java提高篇(十二)-----代码块
在编程过程中我们可能会遇到如下这种形式的程序: public class Test { { //// } } 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起, ...