前序
几乎大部分语言中都有copy这样的函数或者是方法。用于对数据的复制操作。[其中数据类型数组,对象,等]。但是编程序的人,大部分在语言中都会有普通的拷贝方法和deepCopy方法。因此在这里做个叙述,用来介绍这两个方法的区别。
浅拷贝
浅拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这个内存空间的所有指针需要重新定义,不然会造成指针错误。
浅拷贝后的对象(假设为A),如果被拷贝对象(假定为B)的数据发生变化,则A也会跟这发生变化。因此也被称为浅拷贝。不是一种真正的复制。
demo如下:
var obj1=[1,3,4,5,{
age:23,
name: "tangsir"
}];
function copy(ol,or) {
for(var key in ol){
or[key]=ol[key];
}
}
var obj=Object(obj1); // 使用Object进行复制
obj1.age=222; //对obj1 对象的age 属性进行重新赋值
console.log(obj.age); // 222 不再是初始的 23.
深拷贝
深拷贝,就是将需要拷贝的对象的所有内容进行复制一份放入自身对象当中。其中自身对象独立占用一块空间,和被拷贝的对象存储大小无关,并且被拷贝的对象所进行的任何操作都不会影响到自身对象。两个对象之间就是完全独立的关系,无非就是一个对象把另外一个对象的所有数据进行了复制了一份放入自身当中而已。
demo如下:
常规方法
// 采用递归方法实现深拷贝。
function deepclone(obj) {
let objclone = Array.isArray(obj) ? [] : {}; // 生成和目标类型一样的对象。
//判断传入的是否是基本类型。如果是对象类型。则进行递归。
if (obj && typeof obj === "object") { //判断是否为对象。 其中数组和对象 都是object 类型。
for (key in obj) {
if (obj[key] && typeof obj[key] === "object") { // 如果值是对象。则递归调用。
objclone[key] = deepclone(obj[key]);
} else {
objclone[key] = obj[key];
}
}
}
return objclone;
}
var a = [1, 2, 3, 4];
var b = deepclone(a);
b[2] = 1999; // 对b对象的数据进行改变。
console.log(a); // [ 1, 2, 3, 4 ] a对象的数据并未发生变化。
console.log(b); // [ 1, 2, 1999, 4 ]
使用JSON.stringify 结合 JSON.parse 实现深拷贝。
function DeepClone(obj) {
return JSON.parse(JSON.stringify(obj)); // 先将对象变为字符串 然后将字符串 解析为对象 返回。 其中因为字符串类型属于基本类型。基本数据类型不可以改变且存储的位置在栈中。
}
var c = [1, 2, 3, 4,{
age:22}];
var d = DeepClone(c);
d[4].age = 1999;
console.log(c); // [ 1,2,3,4, { age: 22 } ] 由此可见c对象并未因为d的数据发生变化而变化。 两个对象所占用空间彼此独立。因此是深拷贝。
console.log(d); [ 1, 2, 3, 4,{ age: 1999 } ]
总结
既然说了浅拷贝、深拷贝的区别,读者有可能会疑虑既然浅拷贝不是真的复制操作,那么为什么还要它干嘛?正所谓,存在即合理。是时候也总结下应用场景了。由于浅拷贝的特性,JS中浅拷贝适用于基本类型数据和一层结构的数组、对象。[因为基本的数据类型都存放在栈上]。对具有多层结构的数组或者是对象,使用深拷贝。【深拷贝一个多层结构的复杂对象是非常占用内存空间的。】就写这么多了,读者有什么问题,可以在下方留言哦!一起学习进步~~