面试常用——shallowclone、deepclone|深浅克隆区别与方法

浅克隆与深克隆

  • 一、作用
  • 二、区别
  • 三、浅层克隆方法
          • (一)利用for in函数
          • (二)利用Object.assign
          • (三)解构赋值{...obj1}
  • 四、深度克隆
          • (一)JSON.parse(JSON.stringify(object))
          • (二)利用递归函数
  • 五、总结

一、作用

平时项目中我们总会用到一些需要存储备份的时候,这时需要将数组或对象克隆下来,根据需求不同会选择不同的拷贝方式,一般浅拷贝项目中不常用(个人而言)深拷贝的话使用较多,那么他们到底有什么区别呢?

二、区别

很多前端面试中都会涉及到克隆,有时也叫拷贝,一般教程都会从js中的基本数据类型和引用数据类型讲起,很容易查到,我们直接往后说,之前看到过一个说法很容易理解:

浅层克隆只复制一层,深层次的对象级别的克隆引用
深层克隆是拷贝多层,每一级别的数据都会拷贝出来

复杂情况下(对象属性值中存在又是引用值的情况)浅层克隆后,其中一个对象属性值变动都会引起另一个对象属性值的变动,备份肯定是不希望这种情况发生,所以需要深度克隆解决这个问题。

三、浅层克隆方法

校招的时候做过很多面试题都会让我列举出至少两个浅层克隆,不用也需要好好了解一下呀,于是一顿查阅,然后梳理了三个方法供参考。

首先 var 一个原始对象 object 放在那。

 var object = {
     
            myName: "taozi",
            myHabby: "pipa",
            myAge: 20,
            myFamily: ["father", "mother"],
            mywork:{
     
                gowork:"9:00",
                backhome:"22:00"
            }
        }
(一)利用for in函数
		function shallowClone(obj1) {
     
            var obj2 = {
     };
            for (const key in obj1) {
     
                if (object.hasOwnProperty(key)) {
     
                    obj2[key] = obj1[key];
                }
            }
            return obj2;
        }

然后拿myObject装obj2的值

 		var myObject = shallowCopy(object);
        console.log(myObject);

一起康康结果,没问题复制过来了
面试常用——shallowclone、deepclone|深浅克隆区别与方法_第1张图片
再试试改变拷贝过来的对象中数组其中一个值。

        myObject.myFamily[0] = "dad";
        console.log(myObject.myFamily[0]);
        console.log(object.myFamily[0]);

克隆过来的属性值变了,原对象里的属性值也变了。
面试常用——shallowclone、deepclone|深浅克隆区别与方法_第2张图片
说明是浅克隆,同理验证其他两个浅克隆方法。

(二)利用Object.assign
 		var obj1 = Object.assign({
     },object);
        console.log(obj1);
(三)解构赋值{…obj1}
        var obj1 = {
     ...object};
        console.log(obj1);

四、深度克隆

(一)JSON.parse(JSON.stringify(object))
		var obj1 = JSON.parse(JSON.stringify(object));
        console.log(obj1);

还是接着上面浅拷贝我创建了一个object对象,然后执行这段代码
面试常用——shallowclone、deepclone|深浅克隆区别与方法_第3张图片
然后分别检验下object原对象里边的数组(myFamily)和对象(myWork)是否随着原数组改变

        object.myFamily[1] = "mam";
        console.log(obj1.myFamily[1]);
        console.log(object.myFamily[1]);

        obj1.mywork.gowork = "九点";
        console.log(obj1.mywork.gowork);
        console.log(object.mywork.gowork);

面试常用——shallowclone、deepclone|深浅克隆区别与方法_第4张图片
可见,object(原对象)和obj1(克隆对象)中的对象级别属性值不是引用了同一个,所以深度克隆算是成功,但学习过程中发现这种方法有很多开发中可能会遇到的坑,具体可以参考一下
关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑
也可以自行百度。

(二)利用递归函数
		deepClone = obj1 => {
     
            const obj2 = obj1.constructor === Array ? [] : {
     }; 
            for (let key in obj1) {
      
                if (obj1.hasOwnProperty(key)) {
     
                    if (obj1[key] && typeof obj1[key] === 'object') {
      
                        obj2[key] = obj1[key].constructor === Array ? [] : {
     };
                        obj2[key] = deepClone(obj1[key]);
                    } else {
      
                        obj2[key] = obj1[key];
                    }
                }
            }
            return obj2;
        }

        var objectTarget = deepClone(object);

思路是:判断要克隆的是数组还是对象 --> 遍历 --> 如果还有引用类型数据 --> 进入里边遍历每一个属性值 --> 直到里边全是普通类型数据值 --> 将每项添加到obj2中 --> 结束遍历返回obj2的值。

最后检验下

		console.log(object === objectTarget); 
        console.log(object.mywork === objectTarget.mywork); 
        console.log(object.fn === objectTarget.fn);

面试常用——shallowclone、deepclone|深浅克隆区别与方法_第5张图片

五、总结

浅层克隆:

  1. 利用 for in 函数
  2. 利用Object.assign
  3. 解构赋值{…obj1}

深层克隆:

  1. JSON.parse(JSON.stringify(object))
  2. 递归函数

我是程序媛小桃,我在这里记录成长,欢迎多多指正,欢迎一起讨论

你可能感兴趣的:(前端必会,javascript,面试,js)