一、浅拷贝
浅拷贝:只拷贝一层数据; 复杂数据只是拷贝地址;
注意:当对象中还存在复杂数据类型的时候,只会拷贝地址引用,所以新对象对其修改值的时候,还会影响原来的对象中的值;
有三种方式可以实现:
方式一:使用循环遍历对象,将其键值赋值给一个新数组;
// 对象的浅拷贝
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
// 循环遍历数组
for (var k in obj) {
newObj[k] = obj[k];
}
console.log(newObj); //{name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); // 2
console.log(newObj.hobby.a); // 2
方式二:采用Object.assign(新数组,拷贝的数组);方法
// 对象的浅拷贝
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
Object.assign(newObj, obj);
console.log(newObj); // {name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); //2
console.log(newObj.hobby.a); //2
方式三:使用jQuery中的$.extend();方法
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
$.extend(newObj, obj); //将obj复制到新对象中
console.log(newObj); //{name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); //2
console.log(newObj.hobby.a); //2
二、深拷贝
就为了避免拷贝数据之后,引用数据类型之间的相互影响,我们需要深拷贝数据,将引用数据的值拷贝,而不再拷贝其地址;
也有三种方式可以实现;
方式一:使用递归循环拷贝对象;
利用 instanceof 对每一项数据进行类型判断,是否是数组类型,是否是对象类型;如果是,在此基础上,再进行循环;不是 就赋值;
// 对象的浅拷贝
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
//递归循环
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
if (oldObj[k] instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], oldObj[k]);
}
else if (obj[k] instanceof Object) {
newObj[k] = {};
deepCopy(newObj[k], oldObj[k]);
} else {
// 基本数据类型
newObj[k] = oldObj[k];
}
}
}
// 对象深拷贝
deepCopy(newObj, obj);
console.log(newObj); // {name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); // 1
console.log(newObj.hobby.a); // 2
浅拷贝+递归:解决下面的那种方式JSON.parse(JSON.stringify(obj))不能拷贝对象中的方法;而且使用Object.prototype.toString.call(obj)可以准确判断数据的具体类型,不会有偏差,推荐使用;
//浅拷贝+递归:解决JSON.parse(JSON.stringify(obj))不能拷贝对象中的方法
function deepCopy(obj) {
if (Object.prototype.toString.call(obj).slice(8, -1) == 'Object') {
var result = {}
} else if (Object.prototype.toString.call(obj).slice(8, -1) == 'Array') {
var result = []
} //判断数据类型类型
for (var attr in obj) {
if (typeof obj[attr] == 'object') {
result[attr] = deepCopy(obj[attr])
} else {
result[attr] = obj[attr]
}
}
return result
}
方式二:利用JSON.prase()和JSON.stringify()方法 实现对象的深拷贝;
弊端:这一种方式不能拷贝函数!!!
let obj = { "usr": "lisi", "age": 20, fn: function () { console.log('fn...'); } };
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.usr = 'zhangsan';
console.log(obj, obj2); // { usr: 'lisi', age: 20, fn: [Function: fn] } { usr: 'zhangsan', age: 20 }
原理:现将对象转成字符串,然后将字符串转成对象;
// 对象的浅拷贝
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
var objStr = JSON.stringify(obj);
newObj = JSON.parse(objStr);
console.log(newObj); //{name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); //1
console.log(newObj.hobby.a); //2
方式三:利用jQuery中的方法$.extend(true, ...);实现对象的深拷贝; 第一个参数必须为true;
// 对象的浅拷贝
var obj = {
name: '张三',
age: 33,
sex: '男',
hobby: {
a: '1'
}
}
var newObj = {};
$.extend(true, newObj, obj);
console.log(newObj); //{name: "张三", age: 33, sex: "男", hobby: {…}}
newObj.hobby.a = '2';
console.log(obj.hobby.a); //1
console.log(newObj.hobby.a); //2