不要问我心里有没有你,我余光中都是你。——余光中
概念补漏
1. 堆栈的概念
在计算机中,堆栈是两种数据结构。
栈(stack):先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
堆(heap):队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2.基本,引用数据类型
7种基本数据类型: Undefined、Null、Boolean、Number、String、Symbol(es6新增)、BigInt(es10新增), 基本数据类型都存储在栈中,每种数据类型的内存空间大小是确定的,所以便于及时回收,更加容易管理内存空间。
1种引用数据类型: Object 。这其中包含了 object、array、function、date等等,这样的数据存储于堆中。但是其引用类型的数据存储在栈内存中,如果需要访问可以通过先获取到对象的指针地址,然后通过指针地址访问堆中的对应数据。
JavaScript不支持任何创建自定义类型的机制,而所有值最终都将是以上 8 种数据类型之一(排除之后新增)。
为了便于理解我做了一个示范。
堆栈图
3.浅拷贝和深拷贝
浅拷贝:简单的说浅拷贝就是只进行一层的拷贝,对对象的属性第一层进行拷贝,不管之后的层级。
深拷贝:对对象的属性无限层级的拷贝。
代码示范
这是我觉得现在比较好的深浅拷贝方式,随着语言的发展,之后类型的增多,会有一定的增删。
浅拷贝
// shallowCopyconst isObject = (o) => typeof o === 'object' && o !== null;const shallowCopy = (obj) => { if (!isObject(obj)) return obj; const res = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const element = obj[key]; res[key] = element; } } return res;};
深拷贝
// deepCopyconst isObject = (o) => typeof o === 'object' && o !== null;const deepCopy = (obj, weakmap = new WeakMap()) => { if (!isObject(obj)) return obj; // 解决循环引用, 防止无限遍历 if (weakmap.get(obj)) return weakmap.get(obj); // 创建新对象存入weakmap const target = Array.isArray(obj) ? [] : {}; weakmap.set(obj, target); // symbol拷贝 const symArr = Object.getOwnPropertySymbols(obj); symArr.forEach((key) => { if (isObject(obj[key])) { target[key] = deepCopy(obj[key], weakmap); } else target[key] = obj[key]; }); // 对象的key for (const key in obj) { if (obj.hasOwnProperty(key)) { if (isObject(obj[key])) { target[key] = deepCopy(obj[key], weakmap); } else target[key] = obj[key]; } } return target;};
参考文档
WeakMap MDN文档