当前位置: 首页 > Web前端 > JavaScript

理解JavaScript中的内存管理

时间:2023-03-27 12:41:54 JavaScript

在写JavaScript代码的时候,我们很少考虑内存管理(MemoryManagement),因为JS已经帮我们做了这些事情:创建变量(对象,字符串等)来自动分配内存。“自动”释放不再使用的变量,也称为垃圾收集(garbagecollection)。但是了解JS的内存管理,可以在我们遇到内存泄漏问题的时候及时解决,也可以帮助我们写出更高效的代码。什么是内存从计算机硬件的角度来看,内存是计算机的重要组成部分之一,是CPU可以直接寻址的存储空间。计算机中的所有程序都在内存中运行。堆内存和栈内存栈内存(栈内存:栈是JavaScript用来存储静态数据的一种数据结构。静态数据是引擎在编译时知道其大小的数据。在JavaScript中,这包括7个原始值(Primitivevalues)(string,number,boolean,bull,undefined,bigInt,symbol)和对象和函数的引用。特点:栈内存中分配给每个变量的内存空间是固定的。也就是说在栈上分配的空间是在编译时由编译器设置的(这个过程也称为“静态内存分配”),在程序执行时不会改变。栈内存的大小也是有限制的。后进先出,访问speed是相对于Heapmemory,更快堆内存(heapmemory):堆内存是不同的存储数据的空间,javascript在这里存放对象和函数。特点:堆内存的大小是在编译时动态分配的,这个过程也它应该d需要注意的是,当它被称为“动态内存分配”时,堆内存和数据结构中的堆是完全不同的东西,分配方式类似于链表。详情请参考“a”堆和“the”堆有什么关系?访问速度比较慢Staticmemoryallocation&dynamicmemoryallocation:StaticmemoryallocationDynamicmemoryallocationknowsthememorysizewhencompiling不知道编译时的内存大小,在Allocateon-demandwhentheprogramrunningAllocationismadewhen程序运行时分配程序运行时分配栈内存对应堆内存FILO(先进后出)分配没有特定顺序内存生命周期(Memorylifecycle)内存生命周期和的情况在我们的生活中使用工具非常相似。都是取、用、归三个过程。分配内存分配内存发生在我们初始化变量时。使用分配的内存进行读/写操作(Usememory),当不再需要时,释放内存(Releasememory)。当不再需要内存时,必须将其释放(Release)。malloc()和free()函数进行内存管理,JS需要依赖“垃圾回收机制”释放内存varn=12;//分配堆栈内存给Number类型变量nvaro={name:"Emon",job:"developer",};//为对象类型变量o分配堆内存进行存储,并将o的引用存放在栈内存中。垃圾收集(Garbagecollection)垃圾收集的算法主要依赖于引用的概念。引用(Reference):在内存管理环境中,如果一个对象可以访问另一个对象,则称为引用另一个对象的对象。引用包括显式引用和隐式引用。varemonObj={name:"emon",dept:"web"};//emonObj有一个对其原型emonObj.name的隐式引用;//emonObj对象具有对名称值的显式引用,垃圾收集器会在我们不再需要时自动释放内存。但这只能是一个近似的过程,因为“是否还需要一块内存”的状态是不可判定的(undecidable),即算法无法在有限的时间内给出“是”或“否”的答案。因此,判断“是否不再需要”的状态是垃圾回收算法一直在努力考虑和优化的问题。标记清除算法(Mark-and-sweepalgorithm)自2012年以来,所有现代浏览器都使用标记清除垃圾收集算法。它将“是否不再需要该对象”简化为“该对象是否可用”。它的原理是:设置一个名为根(root)的对象(在JavaScript中称为全局对象)。垃圾回收器会定时从根开始,查找所有从根开始引用的对象,以及引用的引用……最后得到所有能获取到的对象和不能获取到的对象,并给出占用的内存因得不到的东西而放手。当然它也有一个局限性,就是无法从根对象中查询到的对象会被清除。引用计数垃圾收集(Reference-countinggarbagecollection)这是最简单的垃圾收集算法,将“是否不再需要该对象”简化为“没有其他对象引用它”。如果一个对象是零引用的,它将被垃圾回收。但是这个算法在有循环引用的时候就不起作用了。因此它已被弃用。我们不会在这里讨论太多。内存泄漏(memoryleak)内存泄漏是指:计算机程序由于某种原因(内存配置管理不当、疏忽或错误)导致程序无法使用不再使用的内存。正在执行的程序无法访问分配给对象的内存。内存泄漏不是指内存在物理上消失,而是应用程序分配了某段内存后,由于设计错误,在打开该段内存之前就失去了对该段内存的控制,造成内存浪费.我们将在这里讨论4个常见的内存泄漏示例,如果您了解幕后发生的事情,您会发现这些很容易避免。全局变量在全局变量中存储数据可能是最常见的内存泄漏。如果你用`var`关键字声明一个变量,直接定义一个`function`,或者直接忽略这个关键字,浏览器引擎会自动把这个变量添加到`window`对象中。functioncreatePerson(){//下面三个变量看似是在createPerson方法中定义的,但实际上是保存在window对象中的。如果数据足够大,会影响程序的运行速度varglobalName="Emon";//使用var关键字创建的变量this.currentPerson="me";//使用this创建的变量,这里this指向的是windowglobalLastName="Lu";//undeclaredvariable}解决方法是尽量避免定义全局变量。您可以使用let和const关键字来定义变量。以严格模式运行代码以避免这种情况。创建全局变量后,一定要在不用的时候释放,可以设置为null。参考文档JavaScript'sMemoryManagementExplainedHowJavaScriptworks:memorymanagement+howtohandle4commonmemoryleaksMemoryManagement