首页 前端知识 深拷贝浅拷贝方法总结

深拷贝浅拷贝方法总结

2024-03-05 09:03:27 前端知识 前端哥 784 132 我要收藏

目录

一、浅拷贝

1.概念:

2.实现方法

2.1 Object.assign(target,…source)

2.2 Array.prototype.slice()

2.3 Array.prototype.concat()

二、深拷贝

1. 概念

2. 实现方法

2.1 _.cloneDeep()

2.2 Json.parse(Json.stringify(obj))

2.3 JQuery中&.extend(deep,{},obj)

2.4 循环递归

一、浅拷贝

1.概念:

       如果属性是基本类型,则为值传递,如果属性是引用类型则拷贝内存地址,即共用内存地址,改变任意一个则另一个内存地址指向也变化。

2.实现方法

  • Object.assign(target,…source)
  • Array.prototype.slice()
  • Array.prototype.concat()

2.1 Object.assign(target,…source)

    var obj1 = {
        name : 'ggg',
        age : 18,
        sex : '女',
        stu : {
            name :'mmm'
        }
    }
    var obj2 = Object.assign({},obj1)
    console.log(obj2)
    obj1.name = 'hhh';
    obj2.stu.name = 'kkk';
    console.log(obj1);
    console.log(obj2);

控制台输出为:

1)、Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象,继承属性和不可枚举属性是不能拷贝的。

2)、针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。

3)、目标对象自身也会改变

4)、异常会打断后续拷贝任务

5)、目前IE浏览器不兼容Object.assign(),如果需要兼容IE的话最好不要直接使用这个方法。

2.2 Array.prototype.slice()

    var arr = ['a','b','c'];
    var arr1 = arr.slice(0)
    console.log(arr1);
    arr1[1] = 'd';
    console.log(arr1);
    console.log(arr);

控制台输出结果为:

2.3 Array.prototype.concat()

   var arr = ['a','b','c'];
    var arr1 = arr.concat()
    console.log(arr1);
    arr[2] = 'd';
    console.log(arr1);
    console.log(arr);

二、深拷贝

1. 概念

        新开辟一个新的栈,所有元素或属性均完全赋值,与源对象完全脱离,对应两个不同的地址,新对象修改不会反映到源对象中。

2. 实现方法

2.1 _.cloneDeep()

const obj2 = _.cloneDeep(obj1);

2.2 Json.parse(Json.stringify(obj))

    const obj2 = JSON.parse(JSON.stringify(obj1));

      但是这种方式存在弊端,会忽略undefinedsymbol函数。

2.3 JQuery中&.extend(deep,{},obj)

使用之前先引入JQuery

<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
var obj1 = {
        name : undefined,
        name2 : 'ggg',
        age  : 18,
        b : { f : { g : 2} },
        c : [ 3,4,5 ],
        d : function() {
            sex = 'nv'
        },
        s : Symbol('A')
    };
    const obj2 = $.extend(true,{},obj1)
    console.log(obj2);
    obj1.age = 45;
    obj2.b.f.g = 7
    console.log(obj1);
    console.log(obj2);

控制台输出:

2.4 循环递归

 // 递归调用
    const deepCopy = (obj) => {
        // 判断传入的值是否为一个对象
        if (obj === null && typeof obj !== "object") {
            return obj;
        }
        // 判断对象的类型 注意这里不考虑包装类对象
        if (Object.prototype.toString.call(obj) === "[object Date]") {
            return new Date(obj);
        }
        if (Object.prototype.toString.call(obj) === "[object RegExp]") {
            return new RegExp(obj);
        }
        if (Object.prototype.toString.call(obj) === "[object Undefined]") {
            return new Error(obj);
        }
        // 判断对象是类
        let newObj = Array.isArray(obj)  ? [] : {}
        for(let item in obj){
            if(typeof obj[item] === 'object') {
                newObj[item] = deepCopy(obj[item])
            }else {
                newObj[item] = obj[item]
            }
        }
        return newObj
    };

    const obj2 = deepCopy(obj1)
    console.log(obj1);
    obj2.age = 25;
    console.log(obj1);
    console.log(obj2);

 控制台输出:

转载请注明出处或者链接地址:https://www.qianduange.cn//article/3281.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!