如何实现深拷贝、浅拷贝?

  • 1、什么是深拷贝、浅拷贝?
  • 2、深拷贝的实现方式
  • 方法1:通过JSON对象实现
  • 方法2:使用递归的方法实现(深拷贝主要还是用递归的方法实现)
  • 方法3:通过jQuery中的extend方法实现
  • 方法4:函数库lodash的_.cloneDeep方法
  • 3、实现浅拷贝的方法
  • 方法1、通过赋值符号 =
  • 方法2:Object.assign()方法
  • 方法3:扩展运算符...


1、什么是深拷贝、浅拷贝?

链接: js中的浅拷贝、深拷贝与赋值的区别

2、深拷贝的实现方式

  深拷贝是针对于引用数据类型

方法1:通过JSON对象实现

  通过JSON.stringify()将对象转为字符串,通过JSON.parse()将字符串转为JSON对象,此时会变成一个新的对象

  此方法的缺点:无法拷贝对象内部的函数

代码示例

let obj = {
    name: '张三',
    address: {
        sheng: "四川",
        shi: "成都"
    },
    sex: "男",
    fun: () => {
        console.log(obj.name);
    }
}
console.log('原obj',obj);
//通过JSON.stringify()将obj转为字符串
let str=JSON.stringify(obj);

// 再通过JSON.parse()将字符串转为JSON对象
let newObj=JSON.parse(str);

console.log('新newObj',newObj);//obj中的函数没有进行拷贝

//修改新对象的值
newObj.name='李四';

console.log('修改属性值后新对象',newObj);
console.log('修改新对象属性值后的原对象',obj);//未发生变化

运行结果

javascript怎么复制json js复制json对象_前端

方法2:使用递归的方法实现(深拷贝主要还是用递归的方法实现)

代码示例:

function deepClone(obj) {
//    判断传递过来形参是不是数组,给objClone赋初始值
    let objClone = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj === 'object') {
        for (let key in obj) {
        //for...in在遍历对象时,遍历的是该对象的整个原型链,结合hasOwnProperty使用,可以只获取对象自身的属性
        //hasOwnProperty()检测一个属性是否属于自身对象
            if (obj.hasOwnProperty(key)) {
            //判断obj子元素是否为对象,如果是,递归复制
                if (obj[key] && typeof obj[key] === 'object') {
                    objClone[key] = deepClone(obj[key]);
                } else {
               	 //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }

        }
    }
    return objClone;
}
let a=[1,2,3,4,{name:"张珊",age:18}];
let b=deepClone(a);
console.log('原数组a',a);
console.log('深拷贝后的新数组b',b);
//对原数组的值进行修改
a[3]=99999;
a[4].age=34567
console.log('修改原数组元素值后的原数组a',a);
console.log('修改原数组元素值后的新数组b',b);

运行结果

javascript怎么复制json js复制json对象_前端_02

方法3:通过jQuery中的extend方法实现

const arr = [1, 2, {key: 'A', label: 'A'}, {key: 'B', label: 'B'}]
    const newArr = $.extend(true, [], arr);
    console.log('newArr',newArr);
    newArr[3].key='我影响原数组了么?';
    newArr[0]=11111;
    console.log('arr',arr);
    console.log('newArr',newArr);

javascript怎么复制json js复制json对象_前端_03

方法4:函数库lodash的_.cloneDeep方法

const lodash=require('lodash');
const obj1={
    name:"张三",
    age:18,
    person:{
        sex:"男",
        height:180
    },
    a:()=>{
        console.log("111");
    }
}
const obj2=lodash.cloneDeep(obj1);
obj2.person.sex="女";
console.log("obj2",obj2);
console.log("obj1",obj1);

javascript怎么复制json js复制json对象_typescript_04

3、实现浅拷贝的方法

方法1、通过赋值符号 =

const obj={name:"张三",age:21};
const obj1=obj;
obj1.age=1888;
console.log("obj", obj);//obj { name: '张三', age: 1888 }
console.log("obj1", obj1);//obj1 { name: '张三', age: 1888 }

方法2:Object.assign()方法

  • 它不会拷贝对象的继承属性;
  • 它不会拷贝对象的不可枚举的属性;
  • 可以拷贝 Symbol 类型的属性。
const obj={name:"张三",age:1};
const obj1=Object.assign(obj);
obj1.age=1111;
obj1.name="Tom"
console.log("obj", obj);//obj { name: 'Tom', age: 1111 }
console.log("obj1", obj1);//obj1 { name: 'Tom', age: 1111 }

方法3:扩展运算符…

  通过扩展运算符进行深拷贝,只能拷贝一层,所以从严格意义上来学不属于深拷贝,属于浅拷贝,注意这个坑

代码示例

onst grades = [
    { key: "A", label: "A" },
    { key: "B", label: "B" },
    { key: "C", label: "C" },
    2,8
]

const copy = [...grades];
console.log("copy", copy);
//对新数组进行修改
copy[1].key="我影响原数组了吗?";
copy[4]=88888;

console.log("grades", grades);
console.log("copy", copy);

运行结果

javascript怎么复制json js复制json对象_typescript_05