一、浅拷贝 浅拷贝:对于基本类型数据来说,拷贝的是值;对于引用数据来说,拷贝了地址,因此拷贝后的对象和原对象会共用一个内存地址,因此,属性值会同步变化(第二层往后的属性)浅拷贝的方法:手写浅拷贝、Object.assign()、拓展运算符 1、手写一个浅拷贝 原始对象的一级属性不会被修改,但是二级往后的属性会被浅拷贝修改本文对js中的浅拷贝与深拷贝做一个小结
function shallowClone(o) {
let newObj = {};
for (let key in o) {
newObj[key] = o[key];
}
return newObj;
}
let obj = {
id:'007',
name:'xxx',
hobby:['eat','sleep','play games'],
foods:{
breakfast:'milk',
lunch:'rice',
dinner:'fish'
}
}
let shallowObj = shallowClone(obj);
shallowObj.id = '110'; //此时原始obj的id不会被改变,因为id是一级属性
shallowObj.hobby[2] = 'study'; //原始obj的hobby中第三个会被改变,因为属于二级属性
shallowObj.foods.dinner = 'apple'; //原始obj的foods中的dinner也会被改变
console.log(shallowObj);
console.log(obj);
结果如下:
let obj = {
id:'007',
name:'xxx',
hobby:['eat','sleep','play games'],
foods:{
breakfast:'milk',
lunch:'rice',
dinner:'fish'
}
}
let newObj = Object.assign({},obj);
newObj.name = 'xyz'; //不会改变原始对象
newObj.foods.lunch = 'none'; //会改变
console.log(obj);
console.log(newObj);
结果如下:
数组使用拓展运算符实现浅拷贝时,第一层的属性不会改变即newObj[0] = ‘drink’ 不会改变原始数组了
let obj = {
id:'007',
name:'xxx',
hobby:['eat','sleep','play games'],
foods:{
breakfast:'milk',
lunch:'rice',
dinner:'fish'
}
}
let newObj = {...obj };
newObj.id = '120'; //不会改变原始对象
newObj.hobby[0] = 'drink'; //会改变原始对象
console.log(newObj);
console.log(obj);
结果为:
对于引用数据类型来说,就是拷贝原始对象的所有属性与方法,在内存中重新开辟一块内存空间进行存储
1、手写一个深拷贝(想直接看深拷贝的可以跳过,这里写出来是为了说明当属性值为数组时,直接递归已经不合适了)
这里:对于对象中属性值为引用数据类型的(数组,对象),采用递归深拷贝的方法。
但是这种方法对于对象中属性值为数组的对象来说,不好用
let obj = {
id: '100',
name: '小栗旬',
hobby: ['drink', 'eat', 'play games'],
address: {
city: '北京市',
area: '海淀区'
}
}
// 手写一个深拷贝
function deepClone(obj) {
let newObj = {};
for (let key in obj) {
// 如果是引用数据类型,就递归深拷贝
if (typeof obj[key] === 'object') {
newObj[key] = deepClone(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
let deepObj = deepClone(obj);
deepObj.id = '10086'; //完全不影响原始对象
deepObj.name = '张学友';
deepObj.hobby[0] = 'study'; //完全不影响
deepObj.address.city = '上海市'; //完全不影响
deepObj.address.area = '静安区'; //完全不影响
console.log(deepObj);
console.log(obj);
对于obj中的hobby来说,不好用,结果为:
function deepClone(obj) {
// 如果传入的是基本类型,则直接返回
if(typeof obj !=='object') {
return obj;
}
let newObj = Array.isArray(obj)?[]:{};
for(let key in obj) {
//保证key不是Object原型上的属性,而是属于obj自身
if(obj.hasOwnProperty(key)) {
//如果obj[key]还是对象,则递归,否则(是数组或基本类型)复制
if(obj[key] && typeof obj[key] === 'object') {
newObj[key] = deepClone(obj[key]);
}else{
newObj[key] = obj[key];
}
}
}
return newObj;
}
let origin1 = null;
let origin2 = {
id:'008',
name:'LULULU',
hobby:['吃饭','睡觉','打游戏'],
address:{
city:'北京市',
area:'朝阳区'
}
}
let deepObj1 = deepClone(origin1);
console.log(origin1,deeoObj1); //当拷贝的原始对象是null时,会返回null的
let deepObj2 = deepClone(origin2);
deepObj2.id = '66666';
deepObj2.name = 'MARK';
deepObj2.hobby[2] = '学习';
deepObj2.address.city = '上海市';
deepObj2.address.area = '静安区';
console.log(deepObj2);
console.log(origin2);
当拷贝空对象时,也会返回空对象,当属性值为数组时,也会进行深拷贝,完全符合要求
结果为:
let obj = {
id:'008',
name:'LULULU',
hobby:['吃饭','睡觉','打游戏'],
address:{
city:'北京市',
area:'朝阳区'
}
}
let newObj = JSON.parse(JSON.stringify(obj));
newObj.name = 'kakaka';
newObj.hobby[0] = '逛街';
newObj.address.area = '海淀区';
console.log(newObj);
console.log(obj);
结果为:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)