zoukankan      html  css  js  c++  java
  • JS的内存机制以及垃圾回收机制

    JS内存空间分为栈、堆、池(一般归并到栈中)

    基本数据类型string、number、boolean、null、undefined保存在栈中

    复杂数据类型object保存在堆中

    常量存放在池中

    js中分配的内存的生命周期为:

    内存分配->内存使用->内存回收

    垃圾回收机制

    js具有自动回收机制,垃圾收集器会按照固定的时间间隔周期性的执行。

    两种方式:

    (1)标记清除

     原理:当变量进入环境时,将这个变量定义为“进入环境”,将变量离开环境时,将其标记为“离开环境”,标记“离开环境”的就回收内存。

     工作流程:

    • 垃圾回收器。在运行的时候给存储在内存中的所有变量都加上标记。
    • 去掉环境中的变量以及被环境中的变量引用的变量(闭包)的标记。
    • 此时仍有标记的变量视为即将要删除的变量
    • 垃圾回收器完成内存清除的工作,销毁那些带标记的值并回收他们所占的内存空间。

    (2)引用计数

    工作原理:跟踪记录每个值被引用的次数

    工作流程:

    • 声明一个变量并将一个引用类型值赋值给这个变量,这个引用类型值的引用次数就是1
    • 同一个引用类型值又被赋值给另一个变量,这个引用类型值的引用次数就加1
    • 当包含这个引用类型值的变量又取得了另一个值,这个引用类型值的引用次数就会减1
    • 当引用次数变为0时,说明没法访问这个值了。
    • 当垃圾回收器下一次运行时就会释放引用次数为0的值所占的内存空间。

    引用计数的问题:循环引用 。循环引用指的是对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。请看下面这个例子

    function problem(){     
        var objectA = new Object();
        var objectB = new Object(); 
     
        objectA.someOtherObject = objectB;
        objectB.anotherObject = objectA; 
    } 

    在这个例子中,objectA 和 objectB 通过各自的属性相互引用;也就是说,这两个对象的引用次数都是 2。

      在采用标记清除策略的实现中,由于函数执行之后,这两个对象都离开了作用域,因此这种相互引用不是个问题。但在采用引用计数策略的实现中,当函数执行完毕后,objectA 和 objectB 还将继续存在,因为它们的引用次数永远不会是 0。

    哪些操作会造成内存泄漏?

    内存泄漏指任何对象在不再拥有或不需要它之后依然存在,即这部分内存用完之后并没有返回到内存池。

    (1)setTimeout第一个参数是字符串而不是函数的时候就会造成内存泄漏

    (2)闭包

    (3)控制台日志

    (4)循环(两个对象彼此引用且彼此保留)

    (5)全局变量

       如果你不断的创建全局变量,不管有没有用到他们,他们都将滞留在程序的整个执行过程中。

    (6)事件监听器

      在页面中创建事件监听器,但是在页面跳转时,又忘记移除这些监听器,那么也可能导致内存泄漏。 

    变量回收规则:

    (1)全局变量不会被回收

    (2)局部变量会被回收,也就是函数一旦运行完,函数内部的变量就会被销毁

    (3)只要被另一个作用域引用就不会被销毁

  • 相关阅读:
    PHP7 网络编程(六)Socket和IO多路复用【待】
    PHP7 网络编程(五)进程间通信【待】
    PHP7 网络编程(四)signal信号【待】
    PHP7 网络编程(三)孤儿进程与僵尸进程
    PHP7 网络编程(二)daemon守护进程
    PHP7 网络编程(一)多进程初探
    为什么要用Rust取代C/C ++重写Python底层?
    Modern Self-Service Data Platforms
    一文读懂量化系统接入及相关平台
    rust asynchronous io:从 mio 到 coroutine
  • 原文地址:https://www.cnblogs.com/xiaoan0705/p/8663203.html
Copyright © 2011-2022 走看看