美文网首页
JavaScript内存管理和垃圾回收

JavaScript内存管理和垃圾回收

作者: MajorDong | 来源:发表于2019-12-06 18:52 被阅读0次

    像c语言这样的底层语言一般都有底层的内存管理接口,如malloc()和free()。相反,JavaScript是在创建变量(对象,字符串...)时自动进行了内存分配,并且在不使用它们时自动释放,释放的过程称为垃圾回收。

    内存生命周期

    不管什么程序语言,内存生命周期基本是一致的:

    1. 分配你所需要的内存
    2. 使用分配到的内存(读、写)
    3. 不需要时将其释放\归还

    所有语言第二部分都是明确的。第一和第三部分在底层语言中是明确的,但在像JavaScript这些高级语言中,大部分都是隐含的。

    JavaScript的内存分配

    值的初始化

    JavaScript在定义变量时就完成了内存分配

    var n = 123; // 给数值变量分配内存
    var s = "azerty"; // 给字符串分配内存
    
    var o = {
      a: 1,
      b: null
    }; // 给对象及其包含的值分配内存
    
    // 给数组及其包含的值分配内存(就像对象一样)
    var a = [1, null, "abra"]; 
    
    function f(a){
      return a + 2;
    } // 给函数(可调用的对象)分配内存
    
    // 函数表达式也能分配一个对象
    someElement.addEventListener('click', function(){
      someElement.style.backgroundColor = 'blue';
    }, false);
    

    通过函数调用内存分配

    有些函数调用结果时分配对象内存

    var d = new Date(); // 分配一个 Date 对象
    
    var e = document.createElement('div'); // 分配一个 DOM 元素(对象)
    

    有些方法分配新变量或者新对象

    var s = "azerty";
    var s2 = s.substr(0, 3); // s2 是一个新的字符串
    // 因为字符串是不变量,
    // JavaScript 可能决定不分配内存,
    // 只是存储了 [0-3] 的范围。
    
    var a = ["ouais ouais", "nan nan"];
    var a2 = ["generation", "nan nan"];
    var a3 = a.concat(a2); 
    // 新数组有四个元素,是 a 连接 a2 的结果
    

    使用值的过程对内存的操作

    使用值的过程实际上是对分配内存进行读取于写入的操作。

    • 可能是写入一个变量或者一个对象的属性值
    • 甚至传递函数的参数

    垃圾回收

    标记-清除算法

    这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。

    这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

    这个算法比前一个要好,因为“有零引用的对象”总是不可获得的,但是相反却不一定,参考“循环引用”。

    从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。

    举个例子

    var fn = function(){}
    document.body.onclick = fn
    var fn = null //fn还是存在于heap内存中
    
    var fn = function(){}
    //fn声明在stack中,存放着它的引用指向在heap中的function(){} 假设引用编号为111
    document.body.onclick = fn
    //document声明在stack中,它存在一个指向heap中body对象的引用 > body中有一个指向heap中onclick的引用 > onclick对象中存在一个对function(){}的引用(引用编号111)。
    var fn = null //在stack中将引用编号111改为了null
    //但function(){}还是存在于heap内存中
    

    相关文章

      网友评论

          本文标题:JavaScript内存管理和垃圾回收

          本文链接:https://www.haomeiwen.com/subject/nsgegctx.html