一, 内存的堆栈
基本类型
存放在栈内存中的简单数据段, 数据大小确定, 内存空间大小可以分配, 当它赋给另一个变量的时候, 另一个变量发生改变, 原数据不会发生改变:
- var a = 5;
- var b = a;
- b += 1;
- console.log(b) //6
- console.log(a) //5
5 种基本数据类型有 Undefined,Null,Boolean,Number 和 String, 它们是直接按值存放的, 所以可以直接访问.
引用类型
存放在堆内存中的对象, 变量实际保存的是一个指针, 这个指针指向另一个位置. 每个空间大小不一样, 要根据情况进行特定的分配. 当我们需要访问引用类型 (如对象, 数组, 函数等) 的值时, 首先从栈中获得该对象的地址指针, 然后再从堆内存中取得所需的数据.
- var a = { userName : 'undefined' };
- var b = a;
- b.userName = 'xiaoming';
- console.log(a); //{userName: "xiaoming"}
- console.log(b); //{userName: "xiaoming"}
上面的例子把 a 的值赋值给 b, 当 b 的值发生改变的时候, a 的值也会跟随改变, 像上面的图解一样, a 和 b 都是指向同一个地址. 如果要让 b 得到一个独立的地址呢? 这就涉及到拷贝了.
二, Object.assign
浅拷贝是复制浅层的引用类型, 比如复制 a = { userName : 'undefined' }这样的对象就是属于浅拷贝, 它只有一层, 像复制 b = { info : { userName : 'undefined' } }这样有嵌套的对象, 多层的引用类型, 就需要用到深拷贝了.
Object.assign()方法可以得到一份浅拷贝的引用类型
- var a = { userName : 'undefined' };
- var b = Object.assign({} , a);
- b.userName = 'xiaoming';
- console.log(a); //{userName: "undefined"}
- console.log(b); //{userName: "xiaoming"}
这样, 我们就能得到一份浅拷贝内容了, 即使是 b 发生改变, 也不会影响到 a, 它们完全是两个独立的个体, 但是此方法不适用深拷贝.
三, 展开运算符
利用展开运算符方法也可以得到一份浅拷贝的引用类型:
- var a = { userName : 'undefined' };
- var b = {...a};
- b.userName = 'xiaoming';
- console.log(a); //{userName: "undefined"}
- console.log(b); //{userName: "xiaoming"}
这样, 我们也能得到一份浅拷贝内容.
四, JSON.parse()&JSON.stringify()
利用 JSON 下面的 parse()方法和 stringify()方法可以得到一份深拷贝内容, 但是这种方法仅适用于对象, stringify()方法可以把对象转变成 JSON 格式的字符串, 再通过 parse()方法进行转译成对象来获得一份拷贝的对象(当然浅拷贝也是适用的):
- var a = { info:{userName : 'undefined'}};
- var b = JSON.parse(JSON.stringify(a));
- b.info.userName = 'xiaoming';
- console.log(a); // { info:{userName : 'undefined'}};
- console.log(b); // { info:{userName : 'xiaoming'}};
五, for...in & 递归(推荐)
这种方法适用于任何引用类型, 原理是使用 for..in 循环, 配合递归函数实现深层拷贝 :
- var a = { info:{userName : 'undefined'}};
- var b = copy(a);
- b.info.userName = 'xiaoming'
- function copy(obj){
- var result = {};
- for(var attr in obj){
- if( typeof obj[attr] === 'object' ){
- result[attr] = copy(obj[attr]);
- }
- else{
- result[attr] = obj[attr];
- }
- }
- return result;
- }
- console.log(a); // { info:{userName : 'undefined'}};
- console.log(b); //{userName: "xiaoming"}
这样, 就可以得到一份深拷贝内容了, 其原理就是层层拷贝, 利用递归的原理, 直到最底层不是对象为止, 好啦, 本次分享就到这里了, 如果有什么不正确的地方, 请各位不吝赐教, 谢谢~
来源: https://www.cnblogs.com/xwkj/p/10127819.html