目录
浅拷贝的例子3:利用Object.assign()方法进行拷贝
1. 浅拷贝概念
针对复杂的数据类型,单独开辟新的内存空间,在栈里面会有地址指向这个空间,拷贝地址
浅拷贝:改变旧的对象的复杂数据类型的值,新的对象的对应值也会改变,借用一个博主的话,拷贝以后复杂数据类型不能够自食其力,就叫浅拷贝。
注意:深浅拷贝概念只针对于 复杂数据类型,数组、对象、函数。
浅拷贝的例子1:for in 进行浅拷贝
var obj = {
name: 'a',
msg: {
age: 18,
}
}
var o = {};
for (var k in obj) {
o[k] = obj[k];
}
console.log(o); // age是19 name还是a
obj.name = 'b';
obj.msg.age = 19;
console.log(obj); // age是19 name是b
console.log(o); // age是19 name是a
修改了obj的msg对象的age值,o对象的也发生变化,复杂数据类型无法自食其力
修改了obj的name值,o对象的没有发生变化,基本数据类型能够 “自食其力”
浅拷贝的例子2:定义数组进行浅拷贝
let a = [1, 2, 3, 4, 5];
let b = a;
a[0] = 3;
console.log(a); // [3, 2, 3, 4, 5]
console.log(b); // [3, 2, 3, 4, 5]
console.log(a === b); // true
总结:
1. a数组赋值给了b数组
2. 紧接着修改a数组的一个值,b的数组也相应的变化,这个也是浅拷贝?这里存疑
浅拷贝的例子3:利用Object.assign()方法进行拷贝
// assign
let obj11 = {
name: 'Lily',
age: '20',
time: ['13', '15'],
person: {
name: 'Henry',
age: '21'
}
};
let obj12 = {
age: '22'
};
let obj13 = Object.assign({}, obj11, obj12);
// 1. 为什么age是22?obj11和obj12都是拷贝源,如果冲突 后面会覆盖前面的
console.log(obj13);
// 2. 不会改变obj11的age
obj13.age = '25';
console.log(obj11.age); // 20
// 3. 会改变obj11的person.age
obj13.person.age = '25'; //
console.log(obj11.person.age); //25
// 4. 会改变obj11的time值
obj13.time[1] = '25'; //
console.log(obj11.time[1]); // 25
首先明确,assign可以有多个参数,第一个永远是目标对象,后面的对象是拷贝来源。
但是注意!
1. 当obj01和obj02都有基本数据类型age时,后面覆盖前面
2. 基本数据类型obj13的age改变了,不会影响obj01的age值。
3. obj13.person.age的值改变了以及obj13.time[1]的值改变了,因为是复杂数据类型对象和数组,所以都会影响obj11和obj12的值。
浅拷贝的例子4:对象的浅拷贝
// 1、 直接赋值 是浅拷贝 数据绑定
let obj01 = {
name: 'Lily',
age: '20',
time: ['13', '15'],
person: {
name: 'Henry',
age: '21'
}
};
let obj02 = obj01; // 直接赋值是浅拷贝
obj02.age = '25'; // 25 会改变obj01的age 无法自食其力
console.log(obj01.age);
obj01.name = '你好';
console.log(obj02.name); // '你好'无法自食其力
obj02.person.age = '25'; //会改变obj01的person.age
console.log(obj01.person.age); // 25
obj02.time[1] = '25'; //会改变obj01的time值
console.log(obj01.time[1]); // 25
注意对象在利用let进行拷贝赋值,也是浅拷贝
但是!,obj01.name和age改变时,也会影响obj02,本来基本数据类型应该是可以自食其力不受影响的。我也给整蒙了,明天再思考。有没有小伙伴出处注意呢?
2. 深拷贝
概念:
newObj拷贝了oldObj的值,拷贝之后,修改newObj的复杂数据类型值,oldObj的复杂数据值不会改变。能够自食其力
逻辑
1. 先判断对象里的元素是数组吗?
1.1 如果是,新对象里面的对应属性的属性值,让其创建一个新数组,递归
1.2 如果不是数组,再判断是不是对象,如果是,新对象对应的属性值,让其创建一个新对象,递归
2. 递归点, oldObj的属性值赋值给newObj对应的属性,newObj[k] = item;
var furn = {
size: '10',
msg: {
size: '100',
msg: {
size: '1000'
}
}
};
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
var item = oldObj[k];
if (item instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], item);
} else if (item instanceof Object) {
newObj[k] = {};
deepCopy(newObj[k], item);
} else {
newObj[k] = item;
}
}
return newObj;
}
console.log(deepCopy(furn));
最终输出的结果,是拷贝之后的元素
另一种写法
function DeepClone(obj) {
if (typeof obj !== 'object' || obj === null) {
debugger
return obj
}
debugger
let result = Array.isArray(obj) ? [] : {}
for (let key in obj) {
debugger
if (obj.hasOwnProperty(key)) {
// 保证key不是原型的属性
result[key] = DeepClone(obj[key])
debugger
}
}
return result
}
3. 浅拷贝和深拷贝的应用:
后台返回一些数据,需要对这些数据进行操作:比如增加、删除、修改、查询等,即便复制了数据对象,
如果是浅拷贝,复杂数据类型,拷贝后修改仍然会影响oldObj
深拷贝,不会影响,更加安全
4. jQuery的深拷贝和浅拷贝extend
如果不加参数,【记住,不加参数,而不是写false】,就是浅拷贝,复杂数据类型是传递地址,拷贝的是地址,拷贝之后新对象不能够自食其力
var oldObj = {
name: 'jmq',
msg: {
age: 20
}
}
var newObj = {};
// 1. 浅拷贝
$.extend(newObj, oldObj);
console.log(newObj); // jmq 19
oldObj.name = 'syc';
oldObj.msg.age = '19';
console.log(oldObj); // syc 19
console.log(newObj); // jmq 19
如果加了参数,true,就是深拷贝,拷贝复杂数据类型,新旧复杂数据类型指向的是不同的地址,不会同时改变
$.extend(true, newObj1, oldObj1);
console.log(newObj1); // jmq 20
oldObj1.name = 'syc';
oldObj1.msg.age = '19';
console.log(oldObj1); // syc 19
console.log(newObj1); // jmq 20
参考文章:
感觉下面这个博主写的特别的详细
js实现数组浅拷贝和深拷贝_xm1037782843的博客-优快云博客_js 数组深拷贝
个人学习id:201903090124-26