当前位置: 首页 > news >正文

前端内存空间(堆、栈、队列、拷贝、垃圾回收)

在了解前端内存空间前,我们先学习三种基本数据结构:堆、栈、队列。

栈是一种线性的数据结构,它遵循后进先出(LIFO)的原则。栈的特点是只能在栈顶进行插入和删除操作,因此栈的底部是栈中的最小值。
栈是自动分配相对固定大小的内存空间、并由系统自动释放

常见算法题应用

有效的括号、删除字符串中的所有相邻重复项…

堆是一种树状的数据结构,每个节点都可以有零个或多个子节点。堆的特点是每个节点的值都大于或等于其子节点的值,因此堆的根节点是堆中的最大值。
堆是动态分配内存、内存大小不固定,也不自动释放,是一种无序的树状结构,满足key-value 键值对的存储方式

队列

队列是一种线性的数据结构,它遵循先进先出(FIFO)的原则。队列的特点是只能在队列的一端进行插入操作,在另一端进行删除操作,因此队列的头部是队列中的最小值。

队列可以在js的事件循环机制中,再深入理解TODO

js数据类型

基本类型

undefined 、null、number、string、boolean、symbol、bigint
值传递,栈内存中存储的是值的拷贝,所以对基本类型的操作不会影响到原变量。

const a = 10;
const b = a;
b = 20;
console.log(a); // 10

引用类型

Object、Array、Function、Date、等等
址传递,堆内存中存储的是地址的拷贝,对引用类型的操作会影响到原变量。

const a = { name: 'Kevin' };
const b = a;
b.name = 'Daisy';
console.log(a.name); // Daisy

深拷贝、浅拷贝

深拷贝

深拷贝是指完全复制一个对象,包括对象的所有属性和方法,以及对象的所有嵌套对象和嵌套数组。
深拷贝会创建一个新的对象,将原对象的所有属性和方法复制到新对象中,并且新对象的所有属性和方法都是新的对象,不会与原对象共享内存。

1、序列化和反序列

问题:undefined、function、symbol这三种类型的值是非安全的(包括该对象的属性循环赋值该对象),所以格式化后,就被过滤掉了,而set、map这种数据格式的对象,也并没有被正确处理,而是处理成了一个空对象。
另外,对于循环引用的对象,会直接报错

const a = { name: 'Kevin', age: 18 };
const b = JSON.parse(JSON.stringify(a));
b.name = 'Daisy';
console.log(a.name); // Kevin
// 循环引用
var data = {name: 'foo',child: null,
}
data.child = data

在这里插入图片描述

2、Object.assign
const a = { name: 'Kevin', age: 18 };
const b = Object.assign({}, a);
b.name = 'Daisy';
console.log(a.name); // Kevin
3、手写深拷贝

需要考虑对象、数组、处理循环引用

/**  class类写法 */
class DeepClone {constructor(){cloneVal: null;}clone(val, map = new WeakMap()) {let type = this.getType(val); //当是引用类型的时候先拿到其确定的类型if (this.isObj(val)) {switch (type) {case 'date':             //日期类型重新new一次传入之前的值,date实例化本身结果不变return new Date(val);break;case 'regexp':           //正则类型直接new一个新的正则传入source和flags即可return new RegExp(val.source, val.flags);break;case 'function':        //如果是函数类型就直接通过function包裹返回一个新的函数,并且改变this指向return new RegExp(val.source, val.flags);break;default:this.cloneVal = Array.isArray(val) ? [] : {};if (map.has(val)) return map.get(val)map.set(val, this.cloneVal)for (let key in val) {if (val.hasOwnProperty(key)) { //判断是不是自身的keythis.cloneVal[key] = new DeepClone().clone(val[key], map);}}return this.cloneVal;}} else {return val;     //当是基本数据类型的时候直接返回}}/** 判断是否是引用类型 */isObj(val) {   return (typeof val == 'object' || typeof val == 'function') && val != null}/** 获取类型 */getType(data) { var s = Object.prototype.toString.call(data);return s.match(/\[object (.*?)\]/)[1].toLowerCase();};
}/** 测试 */
var a ={a:1,b:true,c:undefined,d:null,e:function(a,b){return a + b},f: /\W+/gi,time: new Date(),}
const deepClone = new DeepClone()
let b = deepClone.clone(a)
console.log(b)
4、lodash库

_.cloneDeep()

浅拷贝

浅拷贝是指只复制对象的一层属性,而不复制对象的嵌套属性。

const a = { name: 'Kevin', age: 18 };
const b = {...a };
b.name = 'Daisy';
console.log(a.name); // Kevin

垃圾回收机制

JavaScript中有自动垃圾回收机制,会通过标记清除的算法识别哪些变量对象不再使用,对其进行销毁。开发者也可在代码中手动设置变量值为null(a = null)进行标记清除,让其失去引用,以便下一次垃圾回收时进行有效回收。

堆内存中的对象不会随方法的结束而销毁,就算方法结束了,这个对象也可能会被其他引用变量所引用(参数传递)。创建对象是为了反复利用(因为对象的创建成本通常较大),这个对象将被保存到运行时数据区(也就是堆内存)。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

为什么会有栈内存和堆内存之分?

通常与垃圾回收机制有关。为了使程序运行时占用的内存最小。

当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;

当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

引用计数垃圾收集

如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。
但是当循环引用时,就会出现内存泄漏。

标记清除

垃圾收集器在运行时会给内存中的所有变量都加上一个标记,假设内存中所有对象都是垃圾,全标记为0
然后从各个根对象开始遍历,把不是垃圾的节点改成1
清理所有标记为0的垃圾,销毁并回收它们所占用的内存空间
最后,把所有内存中对象标记修改为0,等待下一轮垃圾回收


http://www.mrgr.cn/news/60286.html

相关文章:

  • C语言小游戏3——扫雷
  • C语言基础题(大合集2)
  • Linux 重启命令全解析:深入理解与应用指南
  • 利用Django实现MySQL数据库的内容在网页的增删改写
  • 软考高级架构师-6.5-NoSQL数据库-超详细讲解+精简总结
  • GoogleChrome的安装和使用
  • 【React】React 18:新特性与重大更新解析
  • Redis安装说明
  • Colorful/七彩虹将星X17 Pro 22 Win11原厂OEM系统 带COLORFUL一键还原
  • 用Spring Boot打造你的网上摄影工作室
  • 《AI 大模型与深度合成技术:安全隐患与应对之策》
  • 靶向赋能 以学促战——山海关公安特邀知名警务教官徐忠宁授课培训
  • 分布式 ID 生成策略(一)
  • AI语音机器人系统的六大特色语音识别呼叫系统部署
  • 基于单片机的便携式快速干衣设备设计
  • phy自协商逻辑和原理
  • OpenCV中的坐标运算 [C#]
  • 终于有人把主数据讲透了!
  • 开发涉及的安全规范整理
  • 【AIGC】从CoT到BoT:AGI推理能力提升24%的技术变革如何驱动ChatGPT未来发展
  • pikachu靶场——垂直越权
  • Pandas数据分析库简介
  • 【设计模式】使用python 实践框架设计
  • 网站域名如何申请?有哪些步骤?
  • 开源项目-拍卖管理系统
  • 轻松部署Dify并实现Ollama与Xinference集成教程!