前言
js拷贝数组对象:浅拷贝&深拷贝,包括:Object.assign、concat、slice、JSON.parse(JSON.stringify())
场景:弹窗选择组织结构(树形结构),选择后显示相关数据至输入框中(每次选择都将重新拷贝初始组织结构数据)
博客地址:芒果橙的个人博客 【http://mangocheng.com】
文章目录
- 前言
- 关于浅拷贝、深拷贝的使用场景
- 常用的拷贝方法
- 场景
- 1. 普通赋值语法-简单数据、复杂数据均为浅拷贝
- 2. Object.assign(target,source)-简单数据深拷贝、复杂数据浅拷贝
- 3. concat()/slice()-简单数据深拷贝、复杂数据浅拷贝
- 4. JSON.parse(JSON.stringify())-简单数据、复杂数据均为深拷贝
- 参考代码
关于浅拷贝、深拷贝的使用场景
在开发过程中,需要基于某一个对象上进行新增修改的场景是非常多的,因此经常会进行对象的拷贝。在不需要多次复用源数据的情况下,那么对象的拷贝只需要进行赋值就能满足要求,即浅拷贝,但有时候需要多次使用到初始的原数组,那么则需要深拷贝,以达到每次拷贝原数组都是初始数据的目的
常用的拷贝方法
场景
弹窗选择组织结构(树形结构),选择后显示相关数据至输入框中
数据格式:[ {},{}]
场景数据,案例使用
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();