有关浅拷贝,深拷贝一直不是很理解,仔细看了一些文档和知识点之后有一些思路和自己的理解,同时还把大学里面学习的知识用到,堆栈,队列等。
js数据类型包括:基本数据类型(Number,String,undefined,Boolean,null),引用数据类型(Array,Object等);浅拷贝,深拷贝是针对引用类型来讲的。
基本类型的名和值都是在栈内存中的,当在赋值时,栈内存都是会新开辟一个内存空间的,所以不存在是不是深拷贝还是浅拷贝。
引用类型的名在栈内存中,值在堆内存中,由栈内存提供一个引用地址指向堆内存中的值,在进行拷贝的时候实际拷贝的是引用地址,并不是实际的值。这时候如果我们想要拷贝值就需要用过浅拷贝和深拷贝。
浅拷贝:复制一层对象的属性,新增了一个新的指针,但是指向了原有的内存地址中,所以如果改变复制的对象时,也会改变原有对象。
常用浅拷贝方法:
1:ES6语法展开运算符…
const c1 = {
name: "jack",
sex: 'man',
age: 20,
hobby: ['play', 'swimming', 'study']
};
const c2 = { ...c1 }
console.log(c2, 'c2')
2:Object.assign()
Object.assign() 方法用于对象的合并,将源对象(souce)的所有可枚举属性,复制到目标对象(target)。然后返回目标对象,返回值为合并后的新对象。Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。
但是Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
注意: 当object只有一层的时候,是深拷贝。
let obj1 = { username: 'jack' }
let obj2 = Object.assign({}, obj1) //将拷贝对象与{}空对象合并
obj2.username = 'mary'
console.log(obj1,'obj1')
console.log(obj2,'obj2')
3:数组 array.concat()
该方法用于数组合并,合并的数组.concat(被合并的数组…);参数可有多个,用逗号分隔,返回合并后的数组。
原理:用原数组去合并一个空数组,返回合并后的数组。
let arr1 = [1, 3, {
username: 'jack'
}];
let arr2 = arr1.concat();
arr2[2].username = 'mary';
arr2[0] = 555;
console.log(arr1,'arr1');
console.log(arr2,'arr2');
4:数组 array.slice()
该方法用途很多,可对数组进行增删,剪裁操作。
const arr1 = [1, 3, { username: 'jack' }]
const arr2 = arr1.slice() //返回剪裁后的数组
arr2[0] = 5
arr2[2].username = 'mary'
console.log('arr1', arr1)
console.log('arr2', arr2)
深拷贝:递归复制所有对象的属性,新增了一个指针的同时申请的一个新的内存地址,让这个新指针指向新的内存地址,所有复制的对象改变之后不影响原对象。
常用的深拷贝方法:
1:使用递归方式实现对数组、对象的拷贝
function deepClone(_obj) {
//根据isArray方法来判断要拷贝的是数组还是对象,来进行不同的处理
var clone_obj = Array.isArray(_obj) ? [] : {};
//判断进行拷贝的是否为空,是否为对象
if (_obj && typeof _obj === "object") {
for (key in _obj) {
if (_obj.hasOwnProperty(key)) {
// 判断拷贝对象中属性值是否存在,是否为对象
if (_obj[key] && typeof _obj[key] === "object") {
clone_obj[key] = deepClone(_obj[key]);// 递归
} else {
clone_obj[key] = _obj[key];
}
}
}
}
return clone_obj;
}
2:JSON.stringify()和JSON.parse(),来进行对数组的深拷贝,但需要注意,比如拷贝的对象里面含有正则,Date对象,Function等时候,会存在问题,无法拷贝出这些属性。比较好的解决方法是使用valueOf()方法,所有对象都包含此方法。
function deepClone(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return cloneObj;
}
3:extends方法
var arr = ['a','b','c','d','e'];
var newArr = $.extend(true,[],arr);
4:Object.assign()
当方法中存在多级属性时是深拷贝,只有一级属性是浅拷贝。
5:lodash.cloneDeep()
lodash.cloneDeep()函数库实现深拷贝