简介
低级语言,比如C,有低级的内存管理基元,像malloc(),free()。另一方面,JavaScript的内存基元在变量(对象,字符串等等)创建时分配,然后在他们不再被使用时“自动”释放。后者被称为垃圾回收。这个“自动”是混淆并给JavaScript(和其他高级语言)开发者一个错觉:他们可以不用考虑内存管理。
内存生命周期
不管什么程序语言,内存生命周期基本一致:
- 分配你所需要的内存
- 使用它(读、写)
- 当它不被使用时释放 ps:和“把大象装冰箱“一个意思
第一二部分过程在所有语言中都很清晰。最后一步在低级语言中很清晰,但是在像JavaScript等高级语言中,最后一步不清晰。
JavaScript的内存分配
变量初始化
为了不让程序员为分配费心,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(); var e = document.createElement('div'); //分配一个DOM元素
有些方法分配新变量或者新对象:
var s = "azerty"; var s2 = s.substr(0, 3); // s2 is a new string //因为string是不变量,JavaScript可能没有分配内存,但只是存储了0-3的范围。 var a = ["ouais ouais", "nan nan"]; var a2 = ["generation", "nan nan"]; var a3 = a.concat(a2); // 新数组中有连接数组a和数组a2中的四个元素。
值的使用
使用值的过程实际上是对分配内存进行读取与写入的操作,这意味着可以写入一个变量或者一个对象的属性值,甚至传递函数的参数。
当内存不再需要使用时释放
大多数内存管理的问题都在这个阶段。在这里最艰难的任务是找到“所分配的内存确实已经不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。
高级语言解释器嵌入了“垃圾回收器”,主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。这个过程是一个近似的,因为要知道某块内存是否需要是 无法判定的 (无法被某种算法所解决).
垃圾回收
如上文所述自动寻找是否一些内存“不再需要”的问题是无法判定的。因此,垃圾回收实现只能有限制的解决一般问题。本节将解释必要的概念,了解主要的垃圾回收算法和它们的局限性。
引用
垃圾回收算法主要依赖于引用的概念。在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如,一个Javascript对象具有对它 原型 的引用(隐式引用)和对它属性的引用(显式引用)。
在这里,“对象”的概念不仅特制Javascript对象,还包括函数作用域(或者全局词法作用域)。
引用计数垃圾收集
这是最简单的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。
例如
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(); // 两个对象被创建,并互相引用,形成了一个循环 // 他们被调用之后不会离开函数作用域 // 所以他们已经没有用了,可以被回收了 // 然而,引用计数算法考虑到他们互相都有至少一次引用,所以他们不会被回收
实际当中的例子
IE 6, 7 对DOM对象进行引用计数回收。对他们来说,一个常见问题就是内存泄露:
var div = document.createElement("div"); div.onclick = function(){ doSomething(); }; // div有了一个引用指向事件处理属性onclick // 事件处理也有一个对div的引用可以在函数作用域中被访问到 // 这个循环引用会导致两个对象都不会被垃圾回收
标记-清除算法
这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。
这个算法假定设置一个叫做根的对象(在Javascript里,根是全局对象)。定期的,垃圾回收器将从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和所有不能获得的对象。
这个算法比前一个要好,因为“有零引用的对象”总是不可获得的,但是相反却不一定,参考“循环引用”。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。
循环引用不再是问题了
第二个示例同样,一旦 div 和其事件处理无法从根获取到,他们将会被垃圾回收器回收
。
限制: 对象需要明确的不可获得
尽管这是一个限制,但是很少会被突破,这也就是为什么在现实中很少人会去关心垃圾回收机制。
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management
相关推荐
由于JavaScript是动态类型语言,其内存管理与编译型语言有所不同,因此理解JS的内存管理和优化对于提升应用程序性能至关重要。 **一、JS内存管理** JS的内存管理主要依赖于垃圾收集机制(Garbage Collection, GC)...
### JavaScript内存管理详解 #### 一、概述 在现代编程语言中,JavaScript 是一种非常流行的脚本语言,广泛应用于Web开发。与C语言或C++这类底层语言不同,JavaScript 不需要程序员手动管理内存,而是自动地进行...
JavaScript的内存管理和闭包是JavaScript编程中的核心概念。在编程中,内存管理是至关重要的,因为它关乎程序的性能和稳定性。JavaScript是一种动态类型的脚本语言,它的内存管理主要是由垃圾回收(Garbage ...
#### JavaScript内存管理概述 JavaScript的内存管理主要包括两个关键部分:内存分配和垃圾回收。 - **内存分配**:在变量或对象创建时分配内存。 - **垃圾回收**:当变量或对象不再被使用时,自动释放其占用的内存...
JavaScript的内存管理主要涉及到栈和堆两种内存区域,以及垃圾回收机制。 栈内存主要用于存储基本数据类型,如数字、字符串、布尔值等,这些数据在声明时直接在栈中分配空间,生命周期较短,当变量的作用域结束时,...
然而,随着Web应用变得越来越复杂,JS内存管理成为了一个关键问题。内存泄露是JS开发者需要特别关注的一个方面,它可能导致应用程序性能下降,甚至崩溃。本文将深入探讨JS内存泄露及其常见实例。 内存泄露通常发生...
JavaScript内存泄漏是一个重要的编程问题,尤其对于Web应用来说,它可能导致性能下降,用户界面响应变慢,甚至在...通过实践和学习,你可以提高自己在JavaScript内存管理方面的技能,从而编写出更加健壮和高效的代码。
### JavaScript内存管理机制 #### 自动内存管理 JavaScript采用自动内存管理机制,这意味着开发者无需手动分配或释放内存。这一特性简化了编程过程,但也可能导致一些难以察觉的问题,比如内存泄漏。 #### 垃圾...
1. **JS内存管理机制** JavaScript使用垃圾回收(Garbage Collection, GC)机制来自动管理内存。当一个变量不再被引用时,GC会将其占用的内存空间回收。然而,循环引用、大量数据结构或长时间存在的全局变量可能...
JavaScript内存管理是前端开发人员必须掌握的知识之一,它关系到程序的性能和稳定性。内存管理包括内存的分配、使用和释放过程,本文将深入浅出地介绍JavaScript的内存生命周期、内存分配机制、函数调用的内存分配,...
### JavaScript 错误认知:无需关注内存管理 #### 前言 JavaScript 是一种广泛使用的高级编程语言,尤其适用于 Web 开发。随着其应用领域的不断扩展,开发者们对其特性的理解也日益深入。然而,有一种常见的误解是...
JavaScript内存管理是编程中的关键环节,它涉及到程序的性能和稳定性。JavaScript是一种高级语言,其内存管理由垃圾回收机制自动处理,但理解这一过程对优化代码和避免内存泄漏至关重要。 内存生命周期在所有编程...
JavaScript的内存管理是其语言特性中的重要组成部分,它与低级语言如C的内存管理机制有着显著的区别。在JavaScript中,内存的分配和回收是由垃圾回收机制自动处理的,这使得开发者无需显式地去释放内存,从而降低了...
附带的ABCJava.Com.url可能是一个链接,指向有关sIEve的更多信息或者JavaScript内存管理的相关教程和资源,这对于深入理解和解决问题非常有帮助。 总的来说,sIEve作为一款JavaScript内存泄漏检测工具,对于提升Web...
1. **JavaScript内存管理** JavaScript的内存管理主要依赖于垃圾回收机制(Garbage Collection, GC)。当一个对象不再有引用指向它时,GC会自动回收这部分内存。然而,在某些情况下,开发者可能无意间创建了全局...
IEJSLeaksDetector是一款专门针对Internet Explorer浏览器的JS内存泄漏检测工具,由于IE浏览器的内存管理机制与其他现代浏览器有所不同,因此它能提供针对性的检测。 在JavaScript中,内存泄漏的常见类型包括: 1....
本文将围绕Node.js内存管理、内存泄露及其排查方法展开讨论。 首先,理解Node.js的内存结构至关重要。V8引擎负责管理JavaScript对象的内存,它将内存划分为不同的区域,如新生区、老生指针区、老生数据区、大对象区...
JavaScript是Web开发中不可或缺的一部分,它负责处理网页的动态交互。深入理解JavaScript的...在阅读“javascript内存浅析”这篇博客后,相信你将对JavaScript内存管理有更深入的理解,并能更好地应对相关的编程挑战。
【Node.js内存管理与内存泄露】 Node.js是一款基于Chrome V8引擎的JavaScript运行环境,以其事件驱动、非阻塞I/O的特性在构建高效、轻量级的Web应用和服务API方面表现出色。由于其高效的开发效率和易扩展性,Node.js...
标题中的“脚本IE内存泄露检测.rar”表明这是一个专门针对Internet Explorer浏览器的JavaScript内存泄漏检测工具。...通过理解JavaScript内存管理机制和利用专业工具,开发者能更有效地避免和修复内存泄漏问题。