js笔记:深拷贝,兼容多种数据类型

浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。

浅拷贝
浅拷贝的意思就是只复制引用,而未复制真正的值。

const originArray = [1,2,3,4,5];
const originObj = {
    
    a:'a',b:'b',c:[1,2,3],d:{
    
    dd:'dd'}};

const cloneArray = originArray;
const cloneObj = originObj;

console.log(cloneArray); // [1,2,3,4,5]
console.log(originObj); // {a:'a',b:'b',c:Array[3],d:{dd:'dd'}}

cloneArray.push(6);
cloneObj.a = {
    
    aa:'aa'};

console.log(cloneArray); // [1,2,3,4,5,6]
console.log(originArray); // [1,2,3,4,5,6]

console.log(cloneObj); // {a:{aa:'aa'},b:'b',c:Array[3],d:{dd:'dd'}}
console.log(originArray); // {a:{aa:'aa'},b:'b',c:Array[3],d:{dd:'dd'}}

上面的代码是最简单的利用 = 赋值操作符实现了一个浅拷贝,可以很清楚的看到,随着 cloneArray 和 cloneObj 改变,originArray 和 originObj 也随着发生了变化。

深拷贝
这个深拷贝自己总结的,可能还存在很多缺点,但是亲测能实现数组,对象,正则,函数,Null,undefined等类型拷贝
代码如下:

 function deepCopy (obj) {
    
    
       // 不是对象(普通值类型/function),null,undefined,正则都会直接返回
       // 这里obj==null  相当于 obj=== null || obj === undefined 的简写形式
       if (typeof obj !== 'object' || obj == null || obj.constructor === RegExp) {
    
    
         return obj;
       }
      var result = Array.isArray(obj)? [] : {
    
    };
       for (var key in obj) {
    
    
         if (obj.hasOwnProperty(key)) {
    
    
           // 是否有key属性,返回布尔值
           // 每个值都验证一次,递归一次
           result[key] = deepCopy(obj[key])
         }
       }
       return result;
     }

对象拷贝测试:

// 定一个多种情况的对象
 var obj1 = {
    
    
       name: 'zs',
       age: 18,
       sex: '男',
       dog: {
    
    
         name: '金毛',
         age: 2,
         yellow: '黄色'
       },
       friends: ['kele','jiawen'],
       say: function () {
    
    
         console.log(1)
       },
       obj: {
    
    
         a: null,
         b: undefined,
         arr:[1,2,3]
       },
       c: /a/,
       d: null,
       e:{
    
    }
     }

     function deepCopy (obj) {
    
    
       // 不是对象(普通值类型/function),null,undefined,正则都会直接返回
       if (typeof obj !== 'object' || obj == null || obj.constructor === RegExp) {
    
    
         return obj;
       }

      var result = Array.isArray(obj)? [] : {
    
    };

       for (var key in obj) {
    
    
         if (obj.hasOwnProperty(key)) {
    
    
           // 是否有key属性,返回布尔值
           // 每个值都验证一次,递归一次
           result[key] = deepCopy(obj[key])
         }
       }
       return result;
       
     }

        var a = deepCopy(obj1);
        a.say()
        // 改动拷贝对象,对比是否实现了深拷贝
        a.name="kele"; // 普通值修改
        a.say = function () {
    
     // 函数修改
          console.log('kele')
        }
        a.say();
        a.dog.name = 'kele'; // 对象改变值
        a.friends.push('xixi') // 数组新加值
        a.e.name="新值" // 空对象新加值
        a.obj.arr.push(8) // 对象里面的数组加值
        a.c = /abc/ // 正则改变值

        // 输出比较
        console.log(a)
        console.log(obj1)

输出:
在这里插入图片描述
数组拷贝测试

		//只贴这部分代码,上面一样
        var arr = [1,2,3,{
    
    name: 'zs',age:20}]
        var newArr = deepCopy(arr);
        newArr[1] = 20;
        newArr[3].name = 'kele';
        newArr.push(88)
        console.log(arr)
        console.log(newArr)

输出:
在这里插入图片描述
总结:平时用这个就可以了,面试写这个也可以了;

其他方法拷贝(都有一些缺点):
Object.assign()
缺点: 当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。

 // 接着来看第二种方式 Object.assign(target, source)
    var obj1 = {
    
    
       name: 'zs',
       age: 18,
       sex: '男',
       dog: {
    
    
         name: '金毛',
         age: 2,
         yellow: '黄色'
       },
       friends: ['kele','jiawen'],
       say: function () {
    
    
         console.log(1)
       },
       obj: {
    
    
         a: null,
         b: undefined,
         arr:[1,2,3]
       },
       c: /a/,
       d: null,
       e:{
    
    }
     }

     var obj2 = Object.assign({
    
    }, obj1);
    // 缺点: 当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。

JSON方法
缺点:使用JSON.stringify()以及JSON.parse()它是不可以拷贝 undefined , function, RegExp 等等类型的

var obj1 = {
    
    
       name: 'zs',
       age: 18,
       sex: '男',
       dog: {
    
    
         name: '金毛',
         age: 2,
         yellow: '黄色'
       },
       friends: ['kele','jiawen'],
       say: function () {
    
    
         console.log(1)
       },
       obj: {
    
    
         a: null,
         b: undefined,
         arr:[1,2,3]
       },
       c: /a/,
       d: null,
       e:{
    
    }
     }
    // 利用JSON方法
    //  缺点:使用JSON.stringify()以及JSON.parse()它是不可以拷贝 undefined , function, RegExp 等等类型的
    function copy (obj) {
    
    
      var start = JSON.stringify(obj); // 返回新字符串,不影响原来对象
      var result = JSON.parse(start);
      return result;

    }
    var a = copy(obj1);
    console.log(a);
    a.friends.push('xixi')
    console.log(obj1)
//     lodash函数库实现深拷贝
// lodash很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝

JQuery实现

var obj1 = {
    
    
       name: 'zs',
       age: 18,
       sex: '男',
       dog: {
    
    
         name: '金毛',
         age: 2,
         yellow: '黄色'
       },
       friends: ['kele','jiawen'],
       say: function () {
    
    
         console.log(1)
       },
       obj: {
    
    
         a: null,
         b: undefined,
         arr:[1,2,3]
       },
       c: /a/,
       d: null,
       e: undefined
     }
     // true进行深拷贝,{}要拷贝到这来
var newArray = $.extend(true,{
    
    },obj1);
// undefined没有拷贝
console.log(newArray)
newArray.dog.name = 'lala'
console.log(obj1)

lodash函数库实现深拷贝
lodash很热门的函数库,提供了 lodash.cloneDeep()实现深拷贝

总结2:如果想更深入去学习。
推荐看这个:
https://github.com/yygmind/blog/issues/29

おすすめ

転載: blog.csdn.net/weixin_45295262/article/details/109594998