内存生命周期

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

所有语言第二部分都是明确的.第一和第三部分在底层语言中是明确的,但在像 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. 分库分表(2) --- ShardingSphere(理论)

    ShardingSphere---理论 ShardingSphere在中小企业需要分库分表的时候用的会比较多,因为它维护成本低,不需要额外增派人手;而且目前社区也还一直在开发和维护,还算是比较活跃. ...

  2. Django之使用redis缓存session,历史浏览记录,首页数据实现性能优化

    Redis缓存session 配置Django缓存数据到redis中 # diango的缓存配置 CACHES = { "default": { "BACKEND&quo ...

  3. Video/audio标签的一些基础使用心得

    常用方法 .play():用于音频视频的播放 .pause():用于音频视频的暂停 常用属性 <audio src="Batmobile Battle Mode Reveal Musi ...

  4. Java匹马行天下之教你用学汉语式方法学编程语言

    Java匹马行天下之教你用学汉语式方法学编程语言 前言: 前段时间接连更新了带小白从入门到了解的几篇博客: <Java匹马行天下之编程常识知多少> <Java匹马行天下之走进编程的殿 ...

  5. Nginx的基本安装配置

    Centos7安装nginx 升级nginx 升级可能遇到问题(我没有遇到, 参考的另一篇文章描述的) 检查nginx版本, 确认安装成功 nginx配置文件 虚拟主机配置 配置文件中可以用的全局变量 ...

  6. (八十五)c#Winform自定义控件-引用区块

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  7. nrm的安装与使用

    nrm的作用:提供了一些最常用的NPM包镜像地址,能够让我们快速的切换安装包时候的服务器地址:,我们依旧使用的事npm的命令,只是镜像地址变了 什么是镜像:原来包刚一开始是只存在于国外的NPM服务器, ...

  8. IMongoQuery的使用-C#

    一.Mongodb的IMongoQuery的使用 引用命名空间:MongoDB.Driver;MongoDB.Driver.Builders; Query.All("name",  ...

  9. bugku--web--输入密码查看flag

    首先打开网页链接 随机五位数的密码爆破,先用python写一个脚本来生成随机五位数: x=range(0,10) f=open("3.txt",'w') for i in x: f ...

  10. Vue中音乐播放器

    一.安装依赖 yarn add vue-aplayer ​ or` npm i vue-aplayer 二.使用 <template> <div class="vue_ap ...