1.关于堆栈
javascript有七种数据类型分别是:String,Number,Boolean,Null,Undefined,Object,Symbol
- 基本类型:String,Number,Boolean,Null,Undefined,Null,Symbol
- 引用类型:Object(Function,Date,Array)
关于栈内存:
- js的基本类型(string,number,boolean,null,undefined,symbol)都是存放在栈内存里面的,其中包括名称还有值,栈是自动分配内存空间大小的,并且由系统自动释放,内存可以及时得到回收。
关于堆内存:
- js的引用类型Object(Function,Array,Date)的值都是存放在堆内存里面,需要主要的是引用类型的名称还有指针都是存在于栈内存中。当我们需要访问引用类型的时候需要先从栈中得到地址指针然后通过地址指针找到堆内存里面的值,可以通过拷贝或者new出来。
下面使用代码说明:
let p1 = [1,2,3,4];
let p2 = p1;
p2[0] = 0;
console.log(p1); // [0,2,3,4]
console.log(p2); // [0,2,3,4]
let str1 = p1[0];
str1 = 6;
console.log(p1); // [0,2,3,4]
- 上面p1是引用类型,当把 p1 复制给 p2 的时候,相当于把地址指针复制给了 p2 ,p2 把这个地址指针存放到栈内存里面,并且这个地址是指向堆内存里面的值的。也就是说p1和p2的地址指向的值是一样。因此p2修改的值的时候相当于是修改了堆内存里面的值。
- str1得到的是基本类型的值,仅仅是从arr1的堆内存里面获取的一个数据,并且存在栈内存里面,所以str1修改的时候,仅仅是在栈中进行修改,而不会影响堆里面的的arr1的数据。
2.js的深浅拷贝
b复制了a,如果我改动了b的值,如果a的值也跟着改变的话就是浅拷贝,如果不会改变的话是深拷贝。
最典型的浅拷贝是 Object.assign:
let obj = {
a: 1,
b: 2
}
let obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj); // {a: 3, b: 2}
console.log(obj1); // {a: 3, b: 2}
深拷贝:
// 重新赋值了 {} 就是深拷贝了
let obj2 = Object.assign({}, obj);
obj2.a = 66;
console.log(obj); // {a: 3, b: 2}
console.log(obj2); // {a: 66, b: 2}
// 关于深拷贝 通过JSON对象
let jsons1 = [1, 2, 3];
let jsons2 = JSON.parse(JSON.stringify(jsons1));
jsons2[0] = 0;
console.log(jsons1); // [1,2,3]
console.log(jsons2); // [0,2,3]