前言
1.1数据类型的复制
基本数据类型的复制,是按值传递的。
let a = 1;
let b = a;
b = 2;
console.log(a);//1
console.log(a);//2
引用数据类型的复制,是按引用传值的。
let obj={
a:1,
b:2
}
let obj1 = obj;
obj1.a=3;
console.log(obj.a);//3
console.log(obj1.a);//3
1.2深拷贝与浅拷贝
深拷贝和浅拷贝都只针对引用数据类型,浅拷贝会对对象逐个成员依次拷贝,但只复制内存地址,而不复制对象本身,新旧对象成员还是共享同一内存;深拷贝会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
两者的区别在于:浅拷贝只是简单的复制,对对象里面的对象属性和数组属性只是复制了地址,并没有创建新的相同对象或者数组。而深拷贝是完完全全的复制一份,空间大小占用一样但是位置不同!
浅拷贝
当把一个对象赋值给一个新的变量时,赋的对象是该对象在栈中的地址,而不是堆中的数据。也就是新旧两个对象指的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,两个对象联动的会一起改变。
1.通过一个空对象进行浅拷贝
let b = {
name: '小明',
age: 18,
home: "天津"
}
let c = {};
function extend(obj1, obj2) {
for (let item in obj1) {
// obj1的值赋值给了obj2
obj2[item] = obj1[item];
}
}
extend(b, c)
c.name = '小红';
c.home = '云南';
console.log(c, b);
2.原型式浅拷贝
let obj1 = {
name: "张三",
say: 'hello'
}
Object.prototype.clone = function () {
let obj = {};
for (item in this) {
obj[item] = this[item];
}
return obj;
}
let obj2 = obj1.clone();
console.log(obj2)
3.Object.assign()方法
let obj1 = {
name: "张三",
say: 'hello'
}
let obj3 = Object.assign({}, obj1);
console.log(obj3)
4.通过三点的方法
let state = {
nickname: '李四',
token: "abcdefg"
}
console.log({ ...state });
5.concat()和slice()
concat()和slice()均为Array原型上的方法,只适用于Array。
let arr1 = [1, 2, { name: '张三' }];
let arr2 = arr1.concat();
arr2[0] = 3;
arr2[2].name = '李四';
console.log('arr1', arr1)
console.log('arr2', arr2)
let arr1 = [1, 2, { name: '张三' }];
let arr2 = arr1.slice();
arr2[0] = 3;
arr2[2].name = '李四';
console.log('arr1', arr1)
console.log('arr2', arr2)
补充说明:Array的slice和contact方法都不会修改原数组,而是会返回一个对原数组进行浅拷贝的新数组。这两种方法同Object.assign()一样,都是对第一层属性依次拷贝,如果第一层的属性是基本数据类型,就拷贝值;如果是引用数据类型,就拷贝内存地址。
深拷贝
把对象的属性中所有引用类型的值,遍历到是基本类型的值为止。
1.JSON.parse(JSON.stringify())方法
JSON.stringify() 将json转换为string类型 可以将前端需要传到后端数据字符串化,JSON.parse() 将json字符串转换为json对象 将后传入到前端的字符串json 对象化
let obj = {
'id': 1,
'name': "杰克",
'msg': {
'age': 10,
'name': '露丝',
'message': {
'id': 10001,
'name': "王五"
}
},
'color': ['red', 'blue', 'green']
}
let obj1 = JSON.parse(JSON.stringify(obj));
obj1.name = "李四";
obj1.msg.age = 20;
obj1.msg.message.id = 10010;
console.log("obj", obj)
console.log("obj1", obj1)
新对象下的数据改变不影响原对象。
缺点:这种方法可以实现数组和对象和基本数据类型的深拷贝,但不能处理函数。因为JSON.stringify()方法是将一个javascript值转换我一个JSON字符串,不能接受函数。
2.通过递归实现深拷贝
let obj = {
'id': 1,
'name': "杰克",
'msg': {
'age': 10,
'name': '露丝',
'message': {
'id': 10001,
'name': "王五"
}
},
'color': ['red', 'blue', 'green']
}
// 递归实现
let obj1 = {}
function fun(newObj, oldObj) {
for (let key in oldObj) {
let item = oldObj[key];
if (item instanceof Array) {
newObj[key] = [];
fun(newObj[key], item)
} else if (item instanceof Object) {
newObj[key] = {};
fun(newObj[key], item);
} else {
newObj[key] = item;
}
}
}
fun(obj1, obj);
console.log(obj1)