深拷贝和浅拷贝

本文详细介绍了JavaScript中对象复制的方法,包括直接赋值、Object.assign()实现浅拷贝,以及JSON.stringify()和递归函数实现深拷贝。还探讨了这些方法在处理复杂对象时的局限性,特别是对于引用类型和特殊值的处理。同时,给出了手动实现深拷贝的函数示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.如何吧对象赋值给另一个对象

一.浅拷贝

1.直接赋值

let obj1 = {
    name:"goubuli"
    age:18
};
let obj2 = obj1;
console.log(obj1,obj2);
obj1.age = 19;
console.log(obj1,obj2)

2.object.assign():合并对象

// 语法:Object.assign(target, ...sources)
// 参数target:必需,目标对象,接收源对象属性的对象,也就是修改后的返回值
// 参数sources:可选,源对象,包含将被合并的属性
// 返回值:目标对象

let target = {
    a: 1,
    b: 2
}

let source = {
    b: 3,
    c: 4
}

Object.assign(target, source);
console.log(target);

// 复制对象

// 写法一
let target2 = {};
Object.assign(target2, source);
console.log(target2);

// 写法二
let returnedTarget = Object.assign({}, source);
console.log(returnedTarget);

// 如果对象属性具有多层嵌套,这时使用Object.assign()复制对象会怎么样呢?Object.assign()真的靠谱吗?

let target3 = {
    a: {
        b: 1,
        c: 2
    },
    e: 4,
    f: 5
}

let source3 = {
    a: {
        b: 1
    },
    e: 2,
    f: 3
}

// 此时你会发现,c属性消失了。说明Object.assign不靠谱,Object.assign对于引用类型的复制也是浅拷贝。

Object.assign(target3, source3);
console.log(target3);

二.深拷贝

1.使用JSON方法  JSON.stringify()讲对象转换为JSON字符串,串行化

let user = {
    name: "jayjun",
    age: 18
};

console.log(user);  // {name: 'jayjun', age: 18}

let userJson = JSON.stringify(user);
console.log(userJson);  // '{"name": "jayjun", "age": 18}'

// JSON.parse() 将JSON字符串转换成对象,反串行化

let user2 = JSON.parse(userJson); 
console.log(user2); // {name: 'jayjun', age: 18}

let target4 = {
    a: {
        b: 1,
        c: 2
    },
    e: 4,
    f: 5
}

let source4 = JSON.parse(JSON.stringify(target4));
console.log(source4);

// 但是这种JSON方式存在弊端,会忽略 undefined、Symbol 和函数。

let obj4 = {
    a: 1,
    b: undefined,
    c: function() {},
    d: Symbol(2)
}

let obj5 = JSON.parse(JSON.stringify(obj4));

console.log(obj4, obj5);

2.如何手写函数实现一个深拷贝?

// 检测类型
let checkType = data => {
    return Object.prototype.toString.call(data).slice(8, -1);
}

// 递归函数实现深拷贝

let deepClone = target => {
    let result; // 存储拷贝结果
    let targetType = checkType(target); // 调用检测类型函数获取target的类型

    // 判断target的类型是否为引用类型
    if (targetType === "Array") {
        result = []; // 如果target是数组类型,则result赋值为[]
    } else if (targetType === "Object") {
        result = {}; // 如果target是对象类型,则result赋值为{}
    } else {
        return target; // 如果target不是引用类型,则直接返回target
    }

    // 遍历 target
    for(let index in target) {
        let value = target[index]; // 获取遍历的value
        let valueType = checkType(value); // 调用检测类型函数获取value类型
        if (valueType === "Array" || valueType === "Object") {
            result[index] = deepClone(value); // 如果是引用类型,则递归调用,并将结果赋值给result[index]
        } else {
            result[index] = value; // 如果不是引用类型,直接将value赋值给result[index]
        }
    }

    return result; // 返回拷贝结果
}

//检测
let target5={
a:{
  b:1,
  c:2
},
e:4,
f:5
}
let result = deepClone(target5)
console.log(result)

let user3={
name:"jayjun",
age:18,
likes:["coding","eating"]
};


let user4 = deepClone(user3);
console.log(user3,user4);

user3.likes[0]="sleeping";
console.log(user3,user4);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值