不要问我心里有没有你,我余光中都是你。——余光中
一直想做个手写的专题,之前也写了一部分,后面会陆陆续续的挪到这里,今天只是写一些相对简单的手写系列,之后会有更加深入的研讨。
概念补漏
1. 堆栈的概念
在计算机中,堆栈是两种数据结构。
- 栈(stack):先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
- 堆(heap):队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2.基本,引用数据类型
- 7种基本数据类型: Undefined、Null、Boolean、Number、String、Symbol(es6新增)、BigInt(es10新增), 基本数据类型都存储在栈中,每种数据类型的内存空间大小是确定的,所以便于及时回收,更加容易管理内存空间。
- 1种引用数据类型: Object 。这其中包含了 object、array、function、date等等,这样的数据存储于堆中。 但是其引用类型的数据存储在栈内存中,如果需要访问可以通过先获取到对象的指针地址,然后通过指针地址访问堆中的对应数据。
JavaScript不支持任何创建自定义类型的机制,而所有值最终都将是以上 8 种数据类型之一(排除之后新增)。
-
为了便于理解我做了一个示范。
-
堆栈图
3.浅拷贝和深拷贝
浅拷贝:简单的说浅拷贝就是只进行一层的拷贝,对对象的属性第一层进行拷贝,不管之后的层级。
深拷贝:对对象的属性无限层级的拷贝。
代码示范
这是我觉得现在比较好的深浅拷贝方式,随着语言的发展,之后类型的增多,会有一定的增删。
- 浅拷贝
// shallowCopy
const 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;
};
- 深拷贝
// deepCopy
const 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;
};