堆栈, JavaScript
1、栈(stack)和堆(heap) stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小也不一定会自动释放
2,数据类型 Js数据类型可以区分为:基本数据类型和引用数据类型 基本数据类型: Number, String, Boolean, Null, Undefined 引用数据类型: Object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)
基本数据类型储存在栈内存中, 在栈内存中的基本数据段, 数据大小确定,内存控件大小可分配, 是直接按照值来存放的,所以直接按照值来访问
let a = "a的值";
let b = a;
b = "b重新赋的值";
console.log(a); // a的值
console.log(b); /let/ b重新赋的值
引用数据类型存储在堆内存中的对象,变量保存在了栈内存中的一个指针上(这个指针就是在堆内存中地址),通过这个指针可以找到堆内存中的对象
let Obj1 = new Object();
var Obj2 = Obj1;
Obj2.name = "名咋";
console.log(Obj1.name);//"名咋"
运行上面代码可以知道, 虽然Obj1把值赋给了Obj2, 但是赋值的只是一份引用地址, 就是说他们用的是在堆内存中同一个位置的对象, 所以修改会导致同步; 如果我不想让他们引用同一个堆内存对象呢, 这就是所谓的深拷贝, 3,深浅拷贝 简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝 比如上面的对象赋值, 赋值了, 但是只给了一个地址. 在堆内存中再开辟一片空间, 把Obj1真正的复制一遍, 这样就是深拷贝 哪些是深拷贝方法哪些是浅拷贝方法? 这就有意思了, 以为有些方法在第一层数据的时候是深拷贝,第两层以及第两层以上的数据就是浅拷贝,哈哈哈 例如: 展开运算符
let a = {ff:{child:"a-ff-child"},ff2:"a-ff2"}
let b = {...a};
b.ff2 = "b-ff2";
b.ff.child = "b-ff-child";
console.log(a)
打印结果: 有兴趣可以用展开运算符试试数组, 结果是相似的;
slice(),concat(),Object.assign()方法与上面的类似,第一层的值修改不会导致赋值对象的修改, 对象中还有对象就会收到影响
深拷贝方法:
1,利用JSON.parse 和JSON.stringfy
let objCopy = JSON.parse(JSON.stringify(obj));
这种深拷贝方法只适用于对象内只包含数组和对象, 如果出现undefined,函数等会出现问题,详情请见https://www.jianshu.com/p/b084dfaad501
|