javascript里面变量再也不使用,就是垃圾,咱们就应该把它清除掉,以避免占用内存。
可是垃圾回收过程是一个近似且不完美的方案,由于某块内存是否还有用,属于“不可断定的”问题,意味着靠算法是解决不了的。
目前主流浏览器使用的是标记清除,在介绍标记清除前先介绍下为何引用计数会被淘汰。javascript
引用计数最先由 Netscape Navigator 3.0 采用,但很快就遇到了严重的问题:循环引用。所谓循环引用,就是对象 A 有一个指针指向对象 B,而对象 B 也引用了对象 A。
html
function problem() { let objectA = new Object(); let objectB = new Object(); objectA.someOtherObject = objectB; objectB.anotherObject = objectA; }
在这个例子中,objectA 和 objectB 经过各自的属性相互引用,意味着它们的引用数都是 2。在 标记清理策略下,这不是问题,由于在函数结束后,这两个对象都不在做用域中。而在引用计数策略下objectA 和 objectB 在函数结束后还会存在,由于它们的引用数永远不会变成 0。若是函数被屡次调 用,则会致使大量内存永远不会被释放。为此,Netscape 在 4.0 版放弃了引用计数,转而采用标记清理。前端
这里介绍下第二步骤的一个实现。
可达性就行可访问性,window(globle)能访问某个变量A(无论经过几层取值),那A就是可达的,那么A就有可能再将来会被用,A就不会被删除。
咱们看一下下图就能明白,左边可达,右边不可达,右边会再某个阶段会v8引擎回收java
明白了垃圾回收的概念,理解闭包就简单多了。
闭包为啥不销毁,由于当前函数执行完的返回值(通常是个函数)被外层上下文中的某个变量引用了,因此闭包中的环境可达,因此不会被销毁。
可是也由于不会被销毁,因此咱们应该注意一下内存泄漏,也就是若是闭包占用的内存特别多,又把它赋给全局变量。并且这个操做咱们是不断的进行的,那个内存就会越占越多,也就是发生了内存泄漏。es6
还有个相关的考点,就是weakmap为何不会被gc(Garbage Collection,垃圾收集)
由于它对于值的引用都是不计入垃圾回收机制的,因此名字里面才会有一个"Weak",表示这是弱引用。
防止内存泄漏咱们须要手动置null。
map的键是对象,这个引用当于永远可达,这样很差,会有内存泄漏。
为了不咱们忘记置Null,es6添加了weakmap这种数据结构,只要所引用的对象的其余引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦再也不须要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用面试
多解除引用(闭包)
优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。若是数据再也不必要,那么把它设置为 null,从而释放其引用。这也能够叫 做解除引用。这个建议最适合全局变量和全局对象的属性。局部变量在超出做用域后会被自动解除引用,算法
1.垃圾回收
2.JavaScript 内存泄漏教程
3.前端面试:谈谈 JS 垃圾回收机制
4.MDN-内存管理
5.javascript高级程序设计第4版本segmentfault