深拷贝与浅拷贝的区别
假如复制A得到了B,如果B中的某个属性发生改变,与此同时如果A中的值也发生改变,叫浅拷贝;
如果A中的值未发生任何变化,叫做深拷贝;
为什么会发生如此变化
主要是因为数据类型的原因
js的数据类型只要分为两大类 基本数据类型(string,number,null,undefined,boolean)与引用类型(object)
深拷贝代码如下
// 将obj2的成员拷贝到obj1中, 只拷贝实例成员
function deepCopy(obj1, obj2) {
for (var key in obj2) {
// 判断是否是obj2上的实例成员
if (obj2.hasOwnProperty(key)) {
// 判断是否是引用类型的成员变量
if (typeof obj2[key] == 'object') {
obj1[key] = Array.isArray(obj2[key]) ? [] : {};
deepCopy(obj1[key], obj2[key]);
} else {
obj1[key] = obj2[key];
}
}
}
}
var person = {
name: 'liyajie',
age: 25,
showName: function() {
console.log(this.name);
},
friends: [1, 2, 3, 4],
family: {
father: 'ligang',
mather: 'sizhongzhen',
wife: 'dan',
baby: 'weijun'
}
}
var student = {};
// 将person的成员拷贝到student对象上.
deepCopy(student, person);
深拷贝方式二:
首先我们要理解 JSON.stringify() 是将一个对象序列化为 JSON 的字符串。即把对象变成一个字符串,如
var obj = {
num:1,
array:[1,2,3]
}
var str = JSON.stringify(obj);
console.log(str); // "{"num":1,"array":[1,2,3]}"
然后 JSON.parse() 将一个 JSON 字符串解析为原生 js 对象。即把字符串转换为对象,如
var objNew = JSON.parse(str);
console.log(objNew); // {num: 1, array: Array(3)}
这行代码的运行过程,就是利用 JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储和传输。(对象本身存储的是一个地址映射,如果断电,对象将不存在,所以要将对象的内容转换成字符串的形式再保存在磁盘上)
不过,这种实现深拷贝的方法有局限性,它只适用于一般数据的拷贝(对象、数组),有以下情况需要注意:
1.如果json里面有时间对象,则序列化结果:时间对象=>字符串的形式;
{
let obj = {
age: 18,
date: new Date()
};
let objCopy = JSON.parse(JSON.stringify(obj));
console.log('obj', obj);
console.log('objCopy', objCopy);
console.log(typeof obj.date); // object
console.log(typeof objCopy.date); // string
}
2.如果json里有RegExp、Error对象,则序列化的结果将只得到空对象 RegExp、Error => {}
{
let obj = {
age: 18,
reg: new RegExp('\\w+'),
err: new Error('error message')
};
let objCopy = JSON.parse(JSON.stringify(obj));
console.log('obj', obj);
console.log('objCopy', objCopy);
}
3.如果json里有 function,undefined,则序列化的结果会把 function,undefined 丢失;
{
let obj = {
age: 18,
fn: function () {
console.log('fn');
},
hh: undefined
};
let objCopy = JSON.parse(JSON.stringify(obj));
console.log('obj', obj);
console.log('objCopy', objCopy);
}
4.如果json里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
{
let obj = {
age: 18,
hh: NaN,
isInfinite: 1.7976931348623157E+10308,
minusInfinity: -1.7976931348623157E+10308
};
let objCopy = JSON.parse(JSON.stringify(obj));
console.log('obj', obj);
console.log('objCopy', objCopy);
}
5.如果json里有对象是由构造函数生成的,则序列化的结果会丢弃对象的 constructor;
{
function Person(name) {
this.name = name;
}
let obj = {
age: 18,
p1: new Person('lxcan')
};
let objCopy = JSON.parse(JSON.stringify(obj));
console.log('obj', obj);
console.log('objCopy', objCopy);
console.log(obj.p1.__proto__.constructor === Person); // true
console.log(objCopy.p1.__proto__.constructor === Object); // true
}