js拷贝数组对象:浅拷贝&深拷贝

前言

js拷贝数组对象:浅拷贝&深拷贝,包括:Object.assign、concat、slice、JSON.parse(JSON.stringify())
场景:弹窗选择组织结构(树形结构),选择后显示相关数据至输入框中(每次选择都将重新拷贝初始组织结构数据)
博客地址:芒果橙的个人博客 【http://mangocheng.com】


关于浅拷贝、深拷贝的使用场景

在开发过程中,需要基于某一个对象上进行新增修改的场景是非常多的,因此经常会进行对象的拷贝。在不需要多次复用源数据的情况下,那么对象的拷贝只需要进行赋值就能满足要求,即浅拷贝,但有时候需要多次使用到初始的原数组,那么则需要深拷贝,以达到每次拷贝原数组都是初始数据的目的

常用的拷贝方法

场景

  • 弹窗选择组织结构(树形结构),选择后显示相关数据至输入框中

  • 数据格式:[ {},{}]

  • 场景数据,案例使用

const copy = {
    // 源数组1:简单数组
	sourceArr: ['a', 'b', 'c'],			
    targetArr: [],
    // 源数组2:复杂数组
    sourceArrAndObj: [					
        {
            'A': 1,
            'B': 2
        },
        {
            'S': 10,
            'T': 20
        }
    ],
    targetArrAndObj: []
}

1. 普通赋值语法-简单数据、复杂数据均为浅拷贝

目标数组=源数组

  • 测试数据
    • 源数组1-sourceArr:[‘a’, ‘b’, ‘c’]
    • 目标数组1-targetArr:[]
    • 源数组2-sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2 }, { ‘S’ : 10, ‘T’ : 20 } ]
    • 目标数组2-targetArrAndObj: []
  • 操作
    • 赋值目标数组
    • 增加目标数组1数据[d、e]
    • 增加目标数组2数据属性[C、D]、修改属性[S、T]
  • 输出
    • 源数组1-sourceArr = a,b,c,d,e
    • 源数组2-sourceArrAndObj = [ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
  • 结果&结论
    • 源数组改变
    • 浅拷贝作用
console.log('sourceArr = ', this.sourceArr.join());
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArr = this.sourceArr;
        this.targetArrAndObj = this.sourceArrAndObj;
        console.log('赋值后:targetArr = ', this.targetArr.join());
        console.log('赋值后:targetArrAndObj=', this.targetArrAndObj);

        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');
        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);

2. Object.assign(target,source)-简单数据深拷贝、复杂数据浅拷贝

Object.assign(目标数组,源数组)

  • 测试简单数据
    • 源数组sourceArr:[‘a’, ‘b’, ‘c’]
    • 目标数组targetArr:[]
  • 操作
    • 增加目标数组数据[d、e]
  • 输出
    • targetArr = a,b,c,d,e
    • sourceArr= a,b,c
  • 结果&结论
    • 源数组未改变
    • 深拷贝作用
console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        Object.assign(this.targetArr, this.sourceArr);
        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());
  • 测试复杂数据
    • 源数组sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2 }, { ‘S’ : 10, ‘T’ : 20 } ]
    • 目标数组targetArrAndObj: []
  • 操作
    • 增加目标数组数据属性[C、D]
    • 修改属性[S、T]
  • 输出
    • sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
    • targetArrAndObj:[ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
  • 结果&结论
    • 源数组改变,与目标数组一样
    • 浅拷贝作用
console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        Object.assign(this.targetArrAndObj, this.sourceArrAndObj);
        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);

3. concat()/slice()-简单数据深拷贝、复杂数据浅拷贝

目标数组=源数组.concat();

目标数组=源数组.slice();

  • 测试简单数据
    • 源数组sourceArr:[‘a’, ‘b’, ‘c’]
    • 目标数组targetArr:[]
  • 操作
    • 增加目标数组数据[d、e]
  • 输出
    • sourceArr= a,b,c
    • targetArr = a,b,c,d,e
  • 结果&结论
    • 源数组未改变
    • 深拷贝作用
console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        this.targetArr = this.sourceArr.concat();
        // this.targetArr = this.sourceArr.slice();

        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());
  • 测试复杂数据
    • 源数组sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2 }, { ‘S’ : 10, ‘T’ : 20 } ]
    • 目标数组targetArrAndObj: []
  • 操作
    • 增加目标数组数据属性[C、D]
    • 修改属性[S、T]
  • 输出
    • sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
    • targetArrAndObj:[ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
  • 结果&结论
    • 源数组改变,与目标数组一样
    • 浅拷贝作用
console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArrAndObj = this.sourceArrAndObj.concat();
        // this.targetArrAndObj = this.sourceArrAndObj.slice();

        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);

4. JSON.parse(JSON.stringify())-简单数据、复杂数据均为深拷贝

目标数组=JSON.parse(JSON.stringify(源数组))

  • 测试简单数据
    • 源数组sourceArr:[‘a’, ‘b’, ‘c’]
    • 目标数组targetArr:[]
  • 操作
    • 增加目标数组数据[d、e]
  • 输出
    • targetArr = a,b,c,d,e
    • sourceArr= a,b,c
  • 结果&结论
    • 源数组未改变
    • 深拷贝作用
console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        this.targetArr = JSON.parse(JSON.stringify(this.sourceArr));

        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());
  • 测试复杂数据
    • 源数组sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2 }, { ‘S’ : 10, ‘T’ : 20 } ]
    • 目标数组targetArrAndObj: []
  • 操作
    • 增加目标数组数据属性[C、D]
    • 修改属性[S、T]
  • 输出
    • sourceArrAndObj:[ { ‘A’ : 1, ‘B’:2 }, { ‘S’ : 10, ‘T’ : 20 } ]
    • targetArrAndObj:[ { ‘A’ : 1, ‘B’:2, ‘C’ : 3, ‘D’ : 4 }, { ‘S’ : 30, ‘T’ : 40 } ]
  • 结果&结论
    • 源数组未改变
    • 深拷贝作用
console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArrAndObj = JSON.parse(JSON.stringify(this.sourceArrAndObj));

        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);

参考代码

const copy = {

    sourceArr: ['a', 'b', 'c'],
    targetArr: [],
    sourceArrAndObj: [
        {
            'A': 1,
            'B': 2
        },
        {
            'S': 10,
            'T': 20
        }
    ],
    targetArrAndObj: [],

    /**
     * = 赋值
     */
    equalSign: function () {

        console.log('sourceArr = ', this.sourceArr.join());
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArr = this.sourceArr;
        this.targetArrAndObj = this.sourceArrAndObj;
        console.log('赋值后:targetArr = ', this.targetArr.join());
        console.log('赋值后:targetArrAndObj=', this.targetArrAndObj);

        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');
        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
    },

    /**
     * Object.assign()
     */
    objectAssign: function () {
        console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        Object.assign(this.targetArr, this.sourceArr);
        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());


        console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        Object.assign(this.targetArrAndObj, this.sourceArrAndObj);
        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);
    },

    /**
     * concat方法
     */
    concataAndSlice: function () {
        console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        this.targetArr = this.sourceArr.concat();
        // this.targetArr = this.sourceArr.slice();

        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());

        console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArrAndObj = this.sourceArrAndObj.concat();
        // this.targetArrAndObj = this.sourceArrAndObj.slice();

        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);
    },

    /**
     * json转换
     */
    json2array: function () {
        console.log('=========简单数组对象=========');
        console.log('sourceArr = ', this.sourceArr.join());
        this.targetArr = JSON.parse(JSON.stringify(this.sourceArr));

        console.log('拷贝后:targetArr = ', this.targetArr.join());
        console.log('=====增加目标数组数据[d、e]');
        this.targetArr.push('d');
        this.targetArr.push('e');

        console.log('更新后:sourceArr = ', this.sourceArr.join());
        console.log('更新后:targetArr = ', this.targetArr.join());

        console.log('=========复杂数组对象=========')
        console.log('sourceArrAndObj=', this.sourceArrAndObj);
        this.targetArrAndObj = JSON.parse(JSON.stringify(this.sourceArrAndObj));

        console.log('拷贝后:targetArrAndObj=', this.targetArrAndObj);
        console.log('=====增加目标数组数据属性[C、D];修改属性[S、T]');

        this.targetArrAndObj[0].C = 3;
        this.targetArrAndObj[0].D = 4;
        this.targetArrAndObj[1].S = 30;
        this.targetArrAndObj[1].T = 40;

        console.log('更新后:sourceArrAndObj=', this.sourceArrAndObj);
        console.log('更新后:targetArrAndObj=', this.targetArrAndObj);

    },


    test: function () {
        this.equalSign();
        // this.objectAssign();
        // this.concataAndSlice();
        // this.json2array();
    }


}

copy.test();

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果-橙

谢谢啦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值