内存(Memory)也被称为内存储器和主存储器,其做用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。计算机中全部程序的运行都是在内存中进行的,所以内存的性能对计算机的影响很是大。javascript
不管什么语言,内存周期基本是一致的:html
值的初始化java
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 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();
JavaScript 中最经常使用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,由于只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。这个算法由如下步骤组成:spa
内存泄漏能够被定义为应用程序再也不须要的内存,可是因为某些缘由不会返回到操做系统或可用内存池。
1. 全局变量
一个未声明变量的引用会在全局对象内部产生一个新的变量。在浏览器的状况,这个全局变量就会是window。
function foo(arg) { bar = "some text"; } 等同于: function foo(arg) { window.bar = "some text"; }
若是bar被指望仅仅在foo函数做用域内保持对变量的引用,而且你忘记使用var去声明它,一个意想不到的全局变量就产生了。
2.被遗忘的计时器和回调
setInterval 在 JavaScript 中是常常被使用的。大多数提供观察者和其余模式的回调函数库都会在调用本身的实例变得没法访问以后对其任何引用也设置为不可访问。 可是在setInterval的状况下,这样的代码很常见:
renderer所表明的对象在将来可能被移除,让部分interval 处理器中代码变得再也不被须要。然而,这个处理器不可以被收集由于interval依然活跃的(这个interval须要被中止从而表面这种状况)。
若是这个interval处理器不可以被收集,那么它的依赖也不可以被收集。这意味这存储大量数据的severData也不可以被收集。
3. 闭包
闭包的特性是内部函数可以访问外部函数的做用域。
var serverData = loadData(); setInterval(function() { var renderer = document.getElementById('renderer'); if(renderer) { renderer.innerHTML = JSON.stringify(serverData); } }, 5000); //每5000ms执行一次
var sayName = function(){ var name = 'jozo'; return function(){ alert(name); } }; var say = sayName(); say();
sayName返回了一个匿名函数,该函数又引用了sayName的局部变量name,sayName 调用后变量name应该被回收,可是因为say继续引用,致使没法回收。
原文出处:https://www.cnblogs.com/hutuzhu/p/11101437.html