深拷贝和浅拷贝


参考链接

浅拷贝

假设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)

jqueryextend()

语法:$.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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值