## 堆与栈
>[success] 堆是动态分配内存,内存大小不一,也不会自动释放。
> 栈是自动分配相对固定大小的内存空间,并由系统自动释放。
### 区别
栈
* 自动分配内存空间,会自动释放。存放基本数据类型的值,引用类型的地址,按值访问,先进后出
* 动态分配的空间一般由程序员分配释放, 若程序员不释放,程序结束时由系统回收
堆
* 动态分配的内存,大小不定,不会自动释放。队列优先,先进先出
* 存放引用数据类型的对象值、函数的参数值,局部变量的值等
* 不允许直接访问、操作堆内存值,引用类型访问的是栈内存中的引用地址;操作对象值时实际上操作的是对象的引用。
![](https://img.kancloud.cn/94/43/94436a88dadc5e3bbe9141c7e1668acb_680x361.png)
### 传值与传址
由于基本类型直接存在在栈内存中,基本类型的使用时,直接获取数据值。引用类型使用时先读取栈中引用地址再读取对应堆中数据值。
## 浅拷贝与深拷贝
浅拷贝
引用类型拷贝时,直接复制值,复制对象与原对象指向同一引用值,更改复制对象值即更改对象引用值,即更改原对象值。
~~~
const obj = { a: 10 };
const copy = obj;
copy.b = 20;
console.log("obj ", obj ); // { a: 10, b: 20 }
console.log("copy ", copy ); // { a: 10, b: 20 }
~~~
深拷贝
1. JSON.parse(JSON.stringify())
> 当有属性值为 undifined 时 JSON.stringify() 方法会将移除该属性
~~~
// JSON.parse(JSON.stringify())
const deepClone = JSON.parse(JSON.stringify(obj));
deepClone.c = 30;
console.log("obj", obj); // { a: 10, b: 20 }
console.log("deepClone", deepClone); // { a: 10, b: 20, c: 30 }
~~~
2. es6语法
~~~
const deepClone = {...obj};
deepClone.c = 30;
console.log("obj", obj); // { a: 10, b: 20 }
console.log("deepClone", deepClone); // { a: 10, b: 20, c: 30 }
~~~
3. deepClone
~~~
function deepClone(obj) {
let newObj;
if (Array.isArray(obj)) {
newObj = obj.map(key => deepClone(obj[key]));
} else if (Object.prototype.toString.call(obj) === "[object Object]") {
newObj = {};
for (const key in obj) {
newObj[key] = deepClone(obj[key]);
}
} else {
newObj = obj;
}
return newObj;
}
~~~
4. 引用第三方库像 loadsh: https://www.lodashjs.com/docs/lodash.cloneDeep