Jump to content
  • Hello visitors, welcome to the Hacker World Forum!

    Red Team 1949  (formerly CHT Attack and Defense Team) In this rapidly changing Internet era, we maintain our original intention and create the best community to jointly exchange network technologies. You can obtain hacker attack and defense skills and knowledge in the forum, or you can join our Telegram communication group to discuss and communicate in real time. All kinds of advertisements are prohibited in the forum. Please register as a registered user to check our usage and privacy policy. Thank you for your cooperation.

    TheHackerWorld Official

JavaScript变量回收原则/垃圾回收机制

 Share


KaiWn

Recommended Posts

先看题目#

下列代码存在几个变量没有被回收?

var i = 1;
var i = 2;
var add = function() {
    var i = 0;
    return function()
{
        i++;
        console.log(i);
    }
}();
add();

答案:3,全局变量有两个,即i和add,局部变量有一个i,因为局部变量被另一个作用域引用,所以局部变量i也不回收

var i = 1;   // 全局变量不会被回收
var i = 2;   // 这里重复声明变量i,因此var声明被忽略,只是把i赋值为2
var add = function() {  // 全局变量不会被回收
    var i = 0;  // 局部变量
    return function() {
        i++;
        console.log(i); // 被另一个作用域引用导致不会被回收
    }
}();
add();

变量回收原则#

  1. 全局变量不会被回收。

  2. 局部变量会被回收,也就是函数一旦运行完以后,函数内部的东西都会被销毁。

  3. 只要被另外一个作用域所引用就不会被回收

JS的垃圾回收机制#

标记清除#

JS中最常见的垃圾回收方式是标记清除
标记清除的概念也好理解,从根部出发看是否能达到某个对象,如果能达到则认定这个对象还被需要,如果无法达到,则释放它,这个过程大致分为三步:

    • 垃圾回收器创建roots列表,roots通常是代码中保留引用的全局变量,在js中,我们一般认定全局对象window作为root,也就是所谓的根部。

    • 从根部出发检查所有 的roots,所有的children也会被递归检查,能从root到达的都会被标记为active。

    • 未被标记为active的数据被认定为不再需要,垃圾回收器开始释放它们。

2059883-20210223153950887-1907136974.gif

注意:
当一个对象零引用时,我们从根部一定无法到达
但反过来,从根部无法到达不一定是严格意义上的零引用,比如循环引用,所以标记清除要更优于引用计数

引用计数#

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

什么情况会引起内存泄漏(无法释放已经不使用的内存)?

虽然有垃圾回收机制但是我们编写代码操作不当还是会造成内存泄漏。
    1. 意外的全局变量引起的内存泄漏。
      原因:全局变量,不会被回收。
      解决:使用严格模式避免。

    2. 闭包引起的内存泄漏
      原因:闭包可以维持函数内局部变量,使其得不到释放。
      解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。

    3. 没有清理的DOM元素引用
      原因:虽然别的地方删除了,但是对象中还存在对dom的引用
      解决:手动删除。

    4. 被遗忘的定时器或者回调
      原因:定时器中有dom的引用,即使dom删除了,但是定时器还在,所以内存中还是有这个dom。
      解决:手动删除定时器和dom。

    5. 子元素存在引用引起的内存泄漏
      原因:div中的ul li 得到这个div,会间接引用某个得到的li,那么此时因为div间接引用li,即使li被清空,也还是在内存中,并且只要li不被删除,他的父元素都不会被删除。
      解决:手动删除清空。

Link to post
Link to comment
Share on other sites

 Share

discussion group

discussion group

    You don't have permission to chat.
    • Recently Browsing   0 members

      • No registered users viewing this page.
    ×
    ×
    • Create New...