参考链接
浅拷贝
假设B复制了A,当修改A时, B也会发生改变
深拷贝
假设B复制了A,当修改A时,B不会发生改变
实现深拷贝
递归复制所有层级的属性
function deepClone(obj){
let target = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for(key in obj) {
if(obj.hasOwnProperty(key)){
// 判断obj子元素的属性值是否为对象
if (obj[key] && typeof obj[key] === "object") {
target[key] = deepClone(obj[key])
} else {
// 如果不是,简单复制
target[key] = obj[key]
}
}
}
}
return target
}
// 测试
let person = {
name: '梦梦',
age : 24,
hobbies: ['吃', '喝', '玩'],
familes: [
{name: '爸爸', age: 42},
{name: '妈妈', age: 41}
]
}
let copyPerson = deepClone(person)
person.hobbies[0] = '吃南瓜'
copyPerson.familes[2] = {name: '妹妹', age: 22}
console.log(person, copyPerson)
【缺点:】递归有溢出的风险.而且需要考虑到不同类型的克隆是不一样的(因此上述只能说是简单的深度克隆的实现)
JSON对象的stringify和parse
function deepClone(obj){
// 将obj引用类型转为基本类型,并赋值给_obj
let _obj = JSON.stringify(obj)
// 将基本类型的_obj转为引用类型,作为返回值
let objClone = JSON.parse(_obj)
return objClone
}
// 测试
let person = {
name: '梦梦',
age : 24,
hobbies: ['吃', '喝', '玩'],
familes: [
{name: '爸爸', age: 42},
{name: '妈妈', age: 41}
]
}
let copyPerson = deepClone(person)
person.hobbies[0] = '吃南瓜'
copyPerson.familes[2] = {name: '妹妹', age: 22}
console.log(person, copyPerson)
【分析:】
JSON.stringify()
:将一个js对象转为json
字符串(引用类型 =》 基本类型)
JSON.parse()
: 将一个json
格式字符串转为js对象(基本类型 =》 引用类型)基本类型拷贝是直接在栈内存新开空间,直接复制一份名-值,两者互不影响。引用数据类型,比如对象,变量名在栈内存,值在堆内存,拷贝只是拷贝了堆内存提供的指向值的地址
而
JSON.stringify()
巧就巧在能将一个对象转换成字符串,也就是基本类型,那这里的原理就是先利用JSON.stringify()
将对象转变成基本数据类型,然后使用了基本类型的拷贝方式,再利用JSON.parse()
将这个字符串还原成一个对象,达到了深拷贝的目的。
JSON.stringify()
对对象的转换,避开了只拷贝地址指向,无法直接拷贝值本身的问题、
【缺点:】JSON.stringify
的方法在深拷贝时是会忽略掉函数与undefined的,因此如果对象里面的属性值是function
则不会被拷贝
JS中对象涵盖比较广,拷贝一个函数,甚至拷贝一个正则对象,都是无法使用JSON方法的,只是在工作中很少深拷贝函数
function deepClone(obj){
// 将obj引用类型转为基本类型,并赋值给_obj
let _obj = JSON.stringify(obj)
// 将基本类型的_obj转为引用类型,作为返回值
let objClone = JSON.parse(_obj)
return objClone
}
// 测试
let person = {
name: '梦梦',
age : 24,
hobbies: ['吃', '喝', '玩'],
familes: [
{name: '爸爸', age: 42},
{name: '妈妈', age: 41}
],
// play属性不会被拷贝到copyPerson里面。(属性丢失)
play: function(){
console.log('跑步')
}
}
let copyPerson = deepClone(person)
console.log(person, copyPerson)
jquery
的extend()
语法:$.extend( [deep ], target, object1 [, objectN ] )
deep
: 可选,是否深拷贝。默认为false
target
: object类型,目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN
:可选。 Object类型 第一个以及第N个被合并的对象。
- 数组的深拷贝
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
// a: [1,1,[2,3],4]
// b: [0,1,[2,3],4]
- 对象深拷贝
let person = {
name: '梦梦',
age : 24,
hobbies: ['吃', '喝', '玩'],
familes: [
{name: '爸爸', age: 42},
{name: '妈妈', age: 41}
]
}
let personClone = $.extend(true, {}, person)
person.hobbies[1] = '喝蜂蜜水'
personClone.familes[2] = {name: '晨晨', age: 16}
console.log(person, personClone)