iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript内存管理介绍是怎样的
  • 644
分享到

JavaScript内存管理介绍是怎样的

2024-04-02 19:04:59 644人浏览 安东尼
摘要

本篇文章为大家展示了javascript内存管理介绍是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。大多数时候,我们在不了解有关内存管理的知识下也只开发,因为

本篇文章为大家展示了javascript内存管理介绍是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

大多数时候,我们在不了解有关内存管理的知识下也只开发,因为 js  引擎会为我们处理这个问题。不过,有时候我们会遇到内存泄漏之类的问题,这个只有知道内存分配是怎样工作的,我们才能解决这些问题。

这里主要介绍内存分配和垃圾回收的工作原理以及如何避免一些常见的内存泄漏问题。

缓存( Memory)生命周期

在 JS 中,当我们创建变量、函数或任何对象时,J S引擎会为此分配内存,并在不再需要时释放它。

分配内存是在内存中保留空间的过程,而释放内存则释放空间,准备用于其他目的。

每次我们分配一个变量或创建一个函数时,该变量的存储会经历以下相同的阶段:

JavaScript内存管理介绍是怎样的

分配内存

  • JS 会为我们处理这个问题:它分配我们创建对象所需的内存。

使用内存

  • 使用内存是我们在代码中显式地做的事情:对内存的读写其实就是对变量的读写。

释放内存

  • 此步骤也由 JS 引擎处理,释放分配的内存后,就可以将其用于新用途。

内存管理上下文中的“对象”不仅包括JS对象,还包括函数和函数作用域。

内存堆和堆

栈现在我们知道,对于我们在 JS 中定义的所有内容,引擎都会分配内存并在不再需要内存时将其释放。

我想到的下一个问题是:这些东西将被储存在哪里?

JS 引擎在两个地方可以存储数据:内存堆和堆栈。堆和堆栈是引擎是用于不同目的的两个数据结构

堆栈:静态内存分配

JavaScript内存管理介绍是怎样的

堆栈是 JS 用于存储静态数据的数据结构。静态数据是引擎在编译时能知道大小的数据。在 JS  中,包括指向对象和函数的原始值(strings,number,boolean,undefined和null)和引用类型。

由于引擎知道大小不会改变,因此它将为每个值分配固定数量的内存。

在执行之前立即分配内存的过程称为静态内存分配。这些值和整个堆栈的限制取决于浏览器。

堆:动态内存分配

堆是另一个存储数据的空间,JS 在其中存储对象和函数。

与堆栈不同,JS 引擎不会为这些对象分配固定数量的内存,而根据需要分配空间。这种分配内存的方式也称为动态内存分配。

下面将对这两个存储的特性进行比较:

堆栈
存放基本类型和引用
大小在编译时已知
分配固定数量的内存
对象和函数
在运行时才知道大小
没怎么限制

事例

来几个事例,加强一下映像。

const person = {   name: 'John',   age: 24, };

JS 在堆中为这个对象分配内存。实际值仍然是原始值,这就是它们存储在堆栈中的原因。

const hobbies = ['hiking', 'reading'];

数组也是对象,这就是为什么它们存储在堆中的原因。

let name = 'John'; // 为字符串分配内存 const age = 24; // 为字分配内存  name = 'John Doe'; // 为新字符串分配内存 const firstName = name.slice(0,4); // 为新字符串分配内存

始值是不可变的,所以 JS 不会更改原始值,而是创建一个新值。

JavaScript 中的引用

所有变量首先指向堆栈。如果是非原始值,则堆栈包含对堆中对象的引用。

堆的内存没有按特定的方式排序,所以我们需要在堆栈中保留对其的引用。我们可以将引用视为地址,并将堆中的对象视为这些地址所属的房屋。

请记住,JS 将对象和函数存储在堆中。基本类型和引用存储在堆栈中。

JavaScript内存管理介绍是怎样的

这张照片中,我们可以观察到如何存储不同的值。注意person和newPerson都如何指向同一对象。

事例

const person = {   name: 'John',   age: 24, };

这将在堆中创建一个新对象,并在堆栈中创建对该对象的引用。

垃圾回收

现在,我们知道 JS 如何为各种对象分配内存,但是在内存生命周期,还有最后一步:释放内存。

就像内存分配一样,JavaScript引擎也为我们处理这一步骤。更具体地说,垃圾收集器负责此工作。

一旦 JS 引擎识别变量或函数不在被需要时,它就会释放它所占用的内存。

这样做的主要问题是,是否仍然需要一些内存是一个无法确定的问题,这意味着不可能有一种算法能够在不再需要那一刻立即收集不再需要的所有内存。

一些算法可以很好地解决这个问题。我将在本节中讨论最常用的方法:引用计数和标记清除算法。

引用计数

当声明了一个变量并将一个引用类型值赋值该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另外一个变量,则该值得引用次数加1。相反,如果包含对这个值引用的变量又取  得了另外一个值,则这个值的引用次数减1。

当这个值的引用次数变成 0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那  些引用次数为零的值所占用的内存。

我们看下面的例子。

JavaScript内存管理介绍是怎样的

请注意,在最后一帧中,只有hobbies留在堆中的,因为最后引用的是对象。

周期数

引用计数算法的问题在于它不考虑循环引用。当一个或多个对象互相引用但无法再通过代码访问它们时,就会发生这种情况。

  1. let son = { 

  2.   name: 'John', 

  3. }; 

  4.  

  5. let dad = { 

  6.   name: 'Johnson', 

  7.  

  8. son.dad = dad; 

  9. dad.son = son; 

  10.  

  11. son = null; 

  12. dad = null; 


JavaScript内存管理介绍是怎样的

由于父对象相互引用,因此该算法不会释放分配的内存,我们再也无法访问这两个对象。

它们设置为null不会使引用计数算法识别出它们不再被使用,因为它们都有传入的引用。

标记清除

标记清除算法对循环依赖性有解决方案。它检测到是否可以从root 对象访问它们,而不是简单地计算对给定对象的引用。

浏览器的root是window 对象,而nodejs中的root是global。

JavaScript内存管理介绍是怎样的

该算法将无法访问的对象标记为垃圾,然后对其进行扫描(收集)。根对象将永远不会被收集。

这样,循环依赖关系就不再是问题了。在前面的示例中,dad对象和son对象都不能从根访问。因此,它们都将被标记为垃圾并被收集。

自2012年以来,该算法已在所有现代浏览器中实现。仅对性能和实现进行了改进,算法的核心思想还是一样的。

折衷

自动垃圾收集使我们可以专注于构建应用程序,而不用浪费时间进行内存管理。但是,我们需要权衡取舍。

内存使用

由于算法无法确切知道什么时候不再需要内存,JS 应用程序可能会使用比实际需要更多的内存。

即使将对象标记为垃圾,也要由垃圾收集器来决定何时以及是否将收集分配的内存。

如果你希望应用程序尽可能提高内存效率,那么最好使用低级语言。但是请记住,这需要权衡取舍。

性能

收集垃圾的算法通常会定期运行以清理未使用的对象。

问题是我们开发人员不知道何时会回收。收集大量垃圾或频繁收集垃圾可能会影响性能。然而,用户或开发人员通常不会注意到这种影响。

内存泄漏

在全局变量中存储数据,最常见内存问题可能是内存泄漏。

在浏览器的 JS 中,如果省略var,const或let,则变量会被加到window对象中。

users = getUsers();

在严格模式下可以避免这种情况。

除了意外地将变量添加到根目录之外,在许多情况下,我们需要这样来使用全局变量,但是一旦不需要时,要记得手动的把它释放了。

释放它很简单,把 null 给它就行了。

window.users = null;

被遗忘的计时器和回调

忘记计时器和回调可以使我们的应用程序的内存使用量增加。特别是在单页应用程序(SPA)中,在动态添加事件侦听器和回调时必须小心。

被遗忘的计时器

const object = {}; const intervalId = setInterval(function() {   // 这里使用的所有东西都无法收集直到清除`setInterval`   doSomething(object); }, 2000);

上面的代码每2秒运行一次该函数。如果我们的项目中有这样的代码,很有可能不需要一直运行它。

只要setInterval没有被取消,则其中的引用对象就不会被垃圾回收。

确保在不再需要时清除它。

clearInterval(intervalId);

被遗忘的回调

假设我们向按钮添加了onclick侦听器,之后该按钮将被删除。旧的浏览器无法收集侦听器,但是如今,这不再是问题。

不过,当我们不再需要事件侦听器时,删除它们仍然是一个好的做法。

const element = document.getElementById('button'); const onClick = () => alert('hi');  element.addEventListener('click', onClick);  element.removeEventListener('click', onClick); element.parentnode.removeChild(element);

脱离DOM引用

内存泄漏与前面的内存泄漏类似:它发生在用 JS 存储DOM元素时。

const elements = []; const element = document.getElementById('button'); elements.push(element);  function removeAllElements() {   elements.forEach((item) => {     document.body.removeChild(document.getElementById(item.id))   }); }

删除这些元素时,我们还需要确保也从数组中删除该元素。否则,将无法收集这些DOM元素。

const elements = []; const element = document.getElementById('button'); elements.push(element);  function removeAllElements() {   elements.forEach((item, index) => {     document.body.removeChild(document.getElementById(item.id));     elements.splice(index, 1);   }); }

由于每个DOM元素也保留对其父节点的引用,因此可以防止垃圾收集器收集元素的父元素和子元素。

上述内容就是JavaScript内存管理介绍是怎样的,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网JavaScript频道。

--结束END--

本文标题: JavaScript内存管理介绍是怎样的

本文链接: https://www.lsjlt.com/news/82237.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript内存管理介绍是怎样的
    本篇文章为大家展示了JavaScript内存管理介绍是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。大多数时候,我们在不了解有关内存管理的知识下也只开发,因为...
    99+
    2024-04-02
  • C++内存管理介绍
    目录1 smart_ptr概述1.1 RAII进制1.2 智能指针1.3 scoped_ptr1.4 scoped_array1.6 shared_array1.7 weak_ptr...
    99+
    2024-04-02
  • JavaScript语法介绍是怎样的
    本篇文章给大家分享的是有关JavaScript语法介绍是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。JavaScript 是一个 脚本...
    99+
    2024-04-02
  • C++技术中的内存管理:内存管理工具和库的介绍
    c++++ 内存管理:内存管理工具:调试器用于识别内存错误;内存分析工具提供内存使用情况见解。内存管理库:智能指针自动管理内存分配和释放,例如 c++11 的 unique_ptr 和 ...
    99+
    2024-05-08
    c++ 内存管理
  • C语言动态内存管理介绍
    目录前言:C 语言为内存的分配和管理提供了几个函数:1.malloc() 用法2.calloc() 用法3.realloc() 与 free() 用法前言: 简单记录一下,内存管理...
    99+
    2024-04-02
  • MSSQL内存架构及管理是怎样的
    本篇文章给大家分享的是有关MSSQL内存架构及管理是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 1.  MSS...
    99+
    2024-04-02
  • Linux系统基本的内存管理知识介绍
    这篇文章主要介绍“Linux系统基本的内存管理知识介绍”,在日常操作中,相信很多人在Linux系统基本的内存管理知识介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux系统基本的内存管理知识介绍”的疑...
    99+
    2023-06-12
  • 关于C语言动态内存管理介绍
    目录1.为什么需要动态内存分配2.有关动态内存函数介绍2.1 malloc和free2.2 calloc函数2.3 realloc函数3. 常见的动态内存错误3.1 对NULL指针进...
    99+
    2024-04-02
  • Linux的内存中Swap和Cache以及Buffer的介绍是怎样的
    Linux的内存中Swap和Cache以及Buffer的介绍是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 total:总内存大小。 used:已经...
    99+
    2023-06-15
  • 关于JavaScript 的对象的介绍是怎样的
    本篇文章为大家展示了关于JavaScript 的对象的介绍是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. 对象方法 & this方法只是保存函数...
    99+
    2024-04-02
  • Monyog的介绍是怎样的
    本篇文章为大家展示了Monyog的介绍是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1、工具强大可以直接定位sql语句在做什么事情;Mysql日志MONyo...
    99+
    2024-04-02
  • JavaScript中null的介绍以及用法是怎样的
    本篇文章给大家分享的是有关JavaScript中null的介绍以及用法是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。JavaScrip...
    99+
    2024-04-02
  • JavaScript中的Map、WeakMap、Set和WeakSet介绍是怎样的
    今天就跟大家聊聊有关JavaScript中的Map、WeakMap、Set和WeakSet介绍是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。...
    99+
    2024-04-02
  • Javascript 高级手势使用的介绍是怎样的
    这期内容当中小编将会给大家带来有关Javascript 高级手势使用的介绍是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。  在IE10中新加入的对高级用...
    99+
    2024-04-02
  • JavaScript内部原理是怎样的
    本篇文章给大家分享的是有关JavaScript内部原理是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。简介Javascript &nbs...
    99+
    2024-04-02
  • Linux内核开发工具介绍是怎么样的
    本篇文章给大家分享的是有关Linux内核开发工具介绍是怎么样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。众所周知,Linux内核是使用make命令来配置并编译的,那必然少不...
    99+
    2023-06-16
  • MySQL explain的介绍是怎样的
    这期内容当中小编将会给大家带来有关MySQL explain的介绍是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。MySQL explain 详解通过 explai...
    99+
    2024-04-02
  • JavaScript内存泄漏的情况是怎样的
    这期内容当中小编将会给大家带来有关JavaScript内存泄漏的情况是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、意外的全局变量。function foo(arg) {&n...
    99+
    2023-06-25
  • Linux内存机制的介绍
    这篇文章主要介绍“Linux内存机制的介绍”,在日常操作中,相信很多人在Linux内存机制的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux内存机制的介绍”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-13
  • Linux是怎么管理内存的
    本篇内容介绍了“Linux是怎么管理内存的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!基本概念每个 Linux 进程都会有地址空间,这些地...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作