Javascript的内存管理

翻译 2016年11月22日 16:16:34

原文地址


介绍

低级语言,像C语言具有能够进行内存管理的工具,比如malloc( )和free( ),另一方面,当一个变量被创建时,javascript的内存会自动分配,当变量不再使用时,也会自动释放。后面的这一过程被称为垃圾回收机制。这种垃圾回收机制是混乱管理的缘由,这给js(或其他高级语言)开发者带来他们能够不去关心内存是如何管理的感觉。这是错误的。


内存的生命周期

不论哪种编程语言,内存的生命周期都是相同的:
  1.  Allocate the memory you need  分配你需要的内存
  2. Use the allocated memory (read, write)  使用分配的内存(读和写)
  3. Release the allocated memory when it is not needed anymore  当你不需要时释放内存

第一二部分在所以语言都是显式的,最后一部分是在低级语言中是显式的,但是在高级语言中却是隐式的,比如JavaScript。


javascript中的内存分配:

1、值得初始化,为了减轻程序员的编程负担,js在分配的时候就声明了值。
2、由函数返回来分配。


使用变量:

使用变量基本上就是读和写分配的内存。我们读写变量的值或者是一个对象的属性,甚至可以传递一个参数给函数来处理。


当不需要的时候释放内存:

大多数内存管理的问题都出现在这个时候,这里最难的就是找到不再需要这块内存的那个时间。通常这都是由开发人员来确定程序中的哪块内存不再需要,并释放它。
高级语言都嵌入了垃圾回收机制,其工作原理是跟踪内存分配和使用,以便找到何时不再需要一块已分配的内存,在这种情况下,它将自动释放。这个过程只能是模糊的,因为程序一般不知道一块内存是否还需要,这是不可判断的(这不能由算法解决)。



垃圾回收机制



如上所述,普遍问题是自动去查找一块分配的内存是否不再需要这是不可判断的。垃圾回收机制实现了如何解决这个问题的限制。本节将帮助理解垃圾回收机制的原理以及局限性。


垃圾回收机制的算法依赖的是引用原理(the notion of reference.)。在内存管理的环境中,一个对象被看做是另一个对象的引用,如果前者对后者具有一个访问(显式或者隐式)。比如,js对象具有对其原型(隐式)和属性(显式)的引用。


这里所说的“对象”的概念扩展到比常规js对象更广泛,并且包含函数作用域(以及全局词法作用域)。


下面接受的是最原始的垃圾回收集算法。该算法将“一个对象不再被需要”定义为“一个对象没有引用它的其他对象”。如果一个对象有0个引用指向,则该对象被认为是可回收的。

var o = { 
  a: {
    b:2
  }
}; 
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'o' variable.
// Obviously, none can be garbage-collected




var o2 = o; // the 'o2' variable is the second thing that 
            // has a reference to the object
o = 1;      // now, the object that was originally in 'o' has a unique reference
            // embodied by the 'o2' variable


var oa = o2.a; // reference to 'a' property of the object.
               // This object has now 2 references: one as a property, 
               // the other as the 'oa' variable


o2 = "yo"; // The object that was originally in 'o' has now zero
           // references to it. It can be garbage-collected.
           // However what was its 'a' property is still referenced by 
           // the 'oa' variable, so it cannot be freed


oa = null; // what was the 'a' property of the object originally in o 
           // has zero references to it. It can be garbage collected.




限制:循环

当该算法涉及到循环时,就会受到限制,下面的事例中,创建了两个对象并且相互引用,从而构建了一个循环。函数调用完毕后,它们讲不会离开函数作用域,所以他们实际上是没有作用的并且应该被释放。然而引用计数算法认为每个对象都被引用了一次,因此没有可以被垃圾回收的对象。

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o references o2
  o2.a = o; // o2 references o


  return "azerty";
}


f();




真实的案例

在ie6、7中已知使用的是DOM对象的引用计数垃圾回收器。循环引用是一个常见的会产生内存泄漏的错误。



var div;
window.onload = function(){
  div = document.getElementById("myDivElement");
  div.circularReference = div;
  div.lotsOfData = new Array(10000).join("*");
};



在上面的示例中,DOM元素“myDivElement”在“circularReference”属性中具有对其自身的循环引用。如果该属性未被明确删除或清空,引用计数的垃圾回收器将始终有一个完整引用,并且将DOM元素保留在内存中,即使它已从DOM树中删除。如果DOM元素保存大量数据(在上面的示例中使用“lotsOfData”属性),则此数据消耗的内存永远不会被释放。


标记和扫描算法



该算法将“对象不再需要”定义归纳为“对象不可达”。
该算法假定知道一组被称为roots的对象(在js中root就是全局对象)。垃圾回收器将定期从这些roots开始查找,然后找到所有从这些roots引用的对象,和所有不被他们引用的对象。从roots开始,垃圾回收器将找到的所有可到达得对象并回收不可到达的对象。

该算法比之前的算法更好,因为“对象零引用”所认为的该对象不可达,相反我们已经看到了循环就知道这不是真的。

截至2012年,所有现代浏览器都装有一个标记清除垃圾回收器。在过去几年中,在JavaScript垃圾回收领域generational/incremental/concurrent/parallel garbage collection)中所做的所有改进都是该算法的实现改进,而不是垃圾回收算法本身的概念, 当“一个对象不再需要”。

循环不再是问题

在上面的第一个例子中,在函数调用返回之后,2个对象不再被从全局对象可达的东西引用。因此,它们将被垃圾回收器发现不可达。

第二个例子也是一样。一旦div和它的处理程序从根无法访问,它们都可以被垃圾回收,尽管引用彼此。

限制:对象需要明确无法访问

虽然这被标记为一个限制,这是一个很少在实践中达到的,这就是为什么没有人经常关心垃圾回收的原因。

相关文章推荐

JavaScript内存管理和优化

在ECMAScript标准中,没有规定任何的内存管理的接口,这使得开发者没有任何的能力来操作内存。但并不代表我们可以不关心内存。 怎样才是一个好的内存管理?简单来说就是做到以下两点 ...
  • Xjl1992
  • Xjl1992
  • 2016年10月13日 14:32
  • 333

JavaScript—内存管理

简介EDIT 诸如 C 语言这般的低级语言一般都有低级的内存管理接口,比如 malloc() 和 free()。而另外一些高级语言,比如 JavaScript, 其在变量(对象,字符串等等)创建时...

JavaScript简单模拟内存管理

这是一道Codewars上的题目,笔者花了一天的时间搞定,在此贴上自己的实现。 原题目的标题是“Simple Memory Manager”,属于4kyu。...
  • esir82
  • esir82
  • 2016年08月05日 10:42
  • 367

JavaScript中的垃圾回收和内存管理

JavaScript中的垃圾回收机制,有两种方法:清除标记法和引用计数法 (1)清除标记法:最常用的一种垃圾回收机制的方法,它是通过将变量进行标记,当变量进行执行流的时候打上一个标记(进入执行环境)...

javascript的垃圾回收机制与内存管理

一、垃圾回收机制—GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。 原理:垃圾收集器会...

JavaScript 内存管理

本文主要是对 V8 之旅: 垃圾回收器 和 JavaScript内存管理和优化 两篇文章的总结v8 垃圾回收垃圾回收器是一把十足的双刃剑。其好处是可以大幅简化程序的内存管理代码,因为内存管理无需程序员...

javascript的内存管理详解

介绍   低层次的语言,如C,具有低级别的内存管理命令,如:malloc()和free(),需要开发者手工释放内存。然而像javascript这样的高级语言情况则不同,对象(objects, str...

javascript 内存管理

前言: 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。【栈】:就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量...

《JavaScript 闯关记》之垃圾回收和内存管理

JavaScript 具有自动垃圾收集机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。而在 C 和 C++ 之类的语言中,开发人员的一项基本...
  • shi0090
  • shi0090
  • 2016年12月29日 20:45
  • 2426

JavaScript学习--Item28 垃圾回收机制与内存管理

1、垃圾回收机制—GCJavascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。原理:垃圾收集器会定期(周期性)找...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Javascript的内存管理
举报原因:
原因补充:

(最多只允许输入30个字)