内存生命周期

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

所有语言第二部分都是明确的.第一和第三部分在底层语言中是明确的,但在像 JavaScript 这些高级语言中,嵌入了'垃圾回收器',根据 Wiki 的定义,垃圾回收是一种自动的内存管理机制,用来追踪不用的内存并自动释放.

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 的结果

使用值

使用值的过程实际上是对分配内存进行读取与写入的操作.读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数.

垃圾回收

程序是运行在内存里的,当声明一个变量、定义一个函数时都会占用内存.内存的容量是有限的,如果变量、函数等只有产生没有消亡的过程,那迟早内存有被完全占用的时候.这个时候,不仅自己的程序无法正常运行,连其他程序也会受到影响.所以,在计算机中,我们需要垃圾回收.需要注意的是,定义中的“自动”的意思是语言可以帮助我们回收内存垃圾,但并不代表我们不用关心内存管理,如果操作失当,JavaScript 中依旧会出现内存溢出的情况.

当一些变量不在需要的时候,javascript 会对该这些变量占用的内存进行释放,而'哪些被分配的内存确实已经不再需要了'是一个难实现的任务.在基础语言中,往往要求开发人员来确定在程序中那一块内存不在需要它之后释放它.而高级语言解释器中嵌入了'垃圾回收器',它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它.垃圾回收实现只能有限制的解决一般问题,因为要知道是否仍然需要某块内存是无法判定的(无法通过某种算法解决).

引用

垃圾回收算法主要依赖于引用的概念.在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象.例如,一个 Javascript 对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用).

在这里,“对象”的概念不仅特指 JavaScript 对象,还包括函数作用域(或者全局词法作用域).

变量

在 js 中有全局变量个局部变量(这里的全局变量是 global object,而 client 中 js 的全局对象指的是 window,也就是当前浏览器窗口).

全局变量在一个浏览器页面中始终是一只存在的.局部变量是在创建它的函数作用域中存在,当离开当前作用域的时候,会自动解除引用并进行释放.

引用计数垃圾收集

这是最初级的垃圾收集算法.此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”.如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收.

var o = {
a: {
b:2
}
};
// 两个对象被创建,一个作为另一个的属性被引用,另一个被分配给变量o
// 很显然,没有一个可以被垃圾收集 var o2 = o; // o2变量是第二个对“这个对象”的引用 o = 1; // 现在,“这个对象”的原始引用o被o2替换了 var oa = o2.a; // 引用“这个对象”的a属性
// 现在,“这个对象”有两个引用了,一个是o2,一个是oa o2 = "yo"; // 最初的对象现在已经是零引用了
// 他可以被垃圾回收了
// 然而它的属性a的对象还在被oa引用,所以还不能回收 oa = null; // a属性的那个对象现在也是零引用了
// 它可以被垃圾回收了

限制:循环引用

该算法有个限制:无法处理循环引用的事例.在下面的例子中,两个对象被创建,并互相引用,形成了一个循环.它们被调用之后会离开函数作用域,所以它们已经没有用了,可以被回收了.然而,引用计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收.

function f(){
var o = {};
var o2 = {};
o.a = o2; // o 引用 o2
o2.a = o; // o2 引用 o return "azerty";
} f();

标记清除算法

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

标记清除算法分为标记和清除两个阶段.这个算法假定设置一个叫做根(root)的对象(在 Javascript 里,根是全局对象).垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象,然后对这些对象进行标记……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象.之后进入了清除阶段,标记的对象会与内存中的对象进行比较,然后清除内存中那些没有标记的对象

  • 标记阶段,它将遍历堆中所有对象,并对存活的对象进行标记;
  • 清除阶段,对未标记对象的空间进行回收.

这是 JavaScript 中最常见的垃圾回收方式.从 2012 年起,所有现代浏览器都使用了标记-清除的垃圾回收方法,低版本 IE 采用的是引用计数方法.

标记整理算法

Mark-Compact (标记整理)算法正是为了解决标记清除所带来的内存碎片的问题,提高对内存的利用.标记整理在标记清除的基础进行修改,标记阶段与标记清除相同,但是对未标记的对象处理方式不同,将其的清除阶段变为紧缩极端.与标记清除是对未标记的对象立即进行回收,标记整理则将活着的对象向内存区的一段移动,移动完成后直接清理掉边界外的内存.紧缩过程涉及对象的移动,所以效率并不是太好,但是能保证不会生成内存碎片.

doc

js垃圾回收的更多相关文章

  1. 前端面试:谈谈 JS 垃圾回收机制

    摘要: 不是每个人都回答的出来... 最近看到一些面试的回顾,不少有被面试官问到谈谈JS 垃圾回收机制,说实话,面试官会问这个问题,说明他最近看到一些关于 JS 垃圾回收机制的相关的文章,为了 B 格 ...

  2. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  3. v8垃圾回收和js垃圾回收机制

    垃圾回收器是一把十足的双刃剑.好处是简化程序的内存管理,内存管理无需程序员来操作,由此也减少了长时间运转的程序的内存泄漏.然而无法预期的停顿,影响了交互体验.本文从 V8 (node.js runti ...

  4. js垃圾回收及内存泄漏

    js垃圾回收 js能够自动回收申请却未使用的内存,由于每次清除需要的性能较大,不是时时在刷新,而是每隔一段时间才进行一次. 回收的两种方式 标记清除(常用) 在内存中先标记变量,然后清除那些那些进入环 ...

  5. js垃圾回收与内存泄漏

    js垃圾回收机制 概念: javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中的使用的内存.而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况 ...

  6. js垃圾回收和内存泄漏

    js垃圾回收和内存泄漏 js垃圾回收 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. 1.标记清除(常用) 工作原理:是当变量进入环境时,将这个变量标记为"进入环境& ...

  7. js 垃圾回收 & js GC

    js 垃圾回收 & js GC js GC / js Garbage Collector https://developer.mozilla.org/en-US/docs/Web/JavaSc ...

  8. 谈谈 JS 垃圾回收机制

    谈谈 JS 垃圾回收机制 JS内存泄漏与垃圾回收机制 https://javascript.info/garbage-collection

  9. 浅尝js垃圾回收机制

    局部作用域内的变量,在函数执行结束之后就会被js的垃圾回收机制销毁   为什么要销毁局部变量? => 为了释放内存   js垃圾回收机制何时会销毁局部变量 : 如果局部变量无法再得到访问,就会被 ...

  10. 闭包内的微观世界和js垃圾回收机制

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

随机推荐

  1. POJ 2533——Longest Ordered Subsequence(DP)

    链接:http://poj.org/problem?id=2533 题解 #include<iostream> using namespace std; ]; //存放数列 ]; //b[ ...

  2. Java 学习笔记之 Stop停止线程

    Stop停止线程: 使用stop()方法停止线程是非常暴力的,会抛出java.lang.ThreadDeath Error,但是我们无需显示捕捉, 以下捕捉只是为了看得更清晰. public clas ...

  3. 如和用python给女朋友做个专属她的软件

    如和用python给女朋友做个专属她的软件 在学习python的路上如果觉得枯燥就可以想我一样做一些有趣的事情就不会无聊了 python是一门及其有趣的语言. 人们都喜欢记住一些重要的日子,比如说跟女 ...

  4. XCTF-CAT

    果然还是我太菜了呜呜呜,这道题仍然是没有自己做出来.哎. 这一道用的并不是PHP的环境,而是用Python中的Django编写的. 记得做过类似的一道题目.来源于MOCTF中的网站扫描器,当时做完后其 ...

  5. PCIE DMA实现

    基于Spartan-6, Virtex-5/Virtex-6/Virtex-7/7 Series FPGA PCI Express Block Endpoint模块设计PCI Express Endp ...

  6. JAVA之类的动手动脑

    1.默认构造方法与自定义的构造方法的冲突 package com.xu; class fool { int value; fool(int nowvalue) { value=nowvalue; } ...

  7. python编程基础之三十四

    面向对象:三大特征:封装,继承,多态 封装:隐藏对象的实现过程,对外仅仅公开接口,控制在程序中的读取和修改的访问级别 类,函数都是一种封装 属性私有化:当类里面的属性不想被外部访问,可以将这些属性设置 ...

  8. Cohen-Sutherland算法

    Cohen-Sutherland算法 本算法又称为编码裁剪算法,算法的基本思想是对每 条直线段分三种情况处理: (1)若点p1和p 2完全在裁剪窗口内 “简取”之 (2)若点p1(x1,y1)和p2( ...

  9. Linux C++轻量级开发指南

    作为一名产品开发,一套顺手的集成开发环境必不可少.大多数时候,开发经理将精力投入在产品需求分析上而忽视了研发质量甚至连基本的集成开发环境都没有统一.当然,如果你们的项目仅仅需要部署在单一的环境中或没有 ...

  10. Python_散点图与折线图绘制

    在数据分析的过程中,经常需要将数据可视化,目前常使用的:散点图  折线图 需要import的外部包  一个是绘图 一个是字体导入 import matplotlib.pyplot as plt fro ...