js 实现对象的拷贝、深拷贝
微wx笑
2021-01-13【前端开发】
164
3
0关键字:
js 对象 拷贝 深拷贝 复制 vue
在使用vue等响应式框架的时候,为了让框架能够监测到数据的改变,我们经常会用到对象的拷贝功能。这里收集了一些实现的方法及注意事项。Object.assign() 基本用法Object.assign
目录
在使用vue等响应式框架的时候,为了让框架能够监测到数据的改变,我们经常会用到对象的拷贝功能。这里收集了一些实现的方法及注意事项。
Object.assign()
基本用法
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
1 2 3 4 5 6 7 | const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3} |
注意点
(1)浅拷贝
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
1 2 3 4 5 | const obj1 = {a: {b: 1}}; const obj2 = Object.assign({}, obj1); obj1.a.b = 2; obj2.a.b // 2 |
上面代码中,源对象obj1的a属性的值是一个对象,Object.assign拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。
方法一:利用JSON.stringify和JSON.parse
1 2 3 4 5 6 7 8 9 10 11 12 13 | let swr = { name: "邵威儒" , age:28, pets:[ '小黄' ] } let swrcopy = JSON.parse(JSON.stringify(swr)) console.log(swrcopy) // { name: '邵威儒', age: 28, pets: [ '小黄' ] } // 此时我们新增swr的属性 swr.pets.push( '旺财' ) console.log(swr) // { name: '邵威儒', age: 28, pets: [ '小黄', '旺财' ] } // 但是swrcopy却不会受swr影响 console.log(swrcopy) // { name: '邵威儒', age: 28, pets: [ '小黄' ] } |
这种方式进行深拷贝,只针对json数据这样的键值对有效
对于函数等等反而无效,不好用,接着继续看方法二、三。
方法二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | function deepCopy(fromObj,toObj) { // 深拷贝函数 // 容错 if (fromObj === null ) return null // 当fromObj为null if (fromObj instanceof RegExp) return new RegExp(fromObj) // 当fromObj为正则 if (fromObj instanceof Date) return new Date(fromObj) // 当fromObj为Date toObj = toObj || {} for (let key in fromObj){ // 遍历 if ( typeof fromObj[key] !== 'object' ){ // 是否为对象 toObj[key] = fromObj[key] // 如果为普通值,则直接赋值 } else { if (fromObj[key] === null ){ toObj[key] = null } else { toObj[key] = new fromObj[key].constructor // 如果为object,则new这个object指向的构造函数 deepCopy(fromObj[key],toObj[key]) // 递归 } } } return toObj } let dog = { name: "小白" , sex: "公" , firends:[ { name: "小黄" , sex: "母" } ] } let dogcopy = deepCopy(dog) // 此时我们把dog的属性进行增加 dog.firends.push({name: "小红" ,sex: "母" }) console.log(dog) // { name: '小白', sex: '公' , firends: [ { name: '小黄' , sex: '母' }, { name: '小红' , sex: '母' } ] } // 当我们打印dogcopy,会发现dogcopy不会受dog的影响 console.log(dogcopy) // { name: '小白', sex: '公' , firends: [ { name: '小黄' , sex: '母' } ] } |
方法三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | let dog = { name: "小白" , sex: "公" , firends:[ { name: "小黄" , sex: "母" } ] } function deepCopy(obj) { if (obj === null ) return null if ( typeof obj !== 'object' ) return obj if (obj instanceof RegExp) return new RegExp(obj) if (obj instanceof Date) return new Date(obj) let newObj = new obj.constructor for (let key in obj){ newObj[key] = deepCopy(obj[key]) } return newObj } let dogcopy = deepCopy(dog) dog.firends.push({name: "小红" ,sex: "母" }) console.log(dogcopy) |
方法四
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function deepClone(data){ var type = getType(data); var obj; if (type === 'array' ){ obj = []; } else if (type === 'object' ){ obj = {}; } else { //不再具有下一层次 return data; } if (type === 'array' ){ for ( var i = 0, len = data.length; i < len; i++){ obj.push(deepClone(data[i])); } } else if (type === 'object' ){ for ( var key in data){ obj[key] = deepClone(data[key]); } } return obj; } |
相关参考:
【ES6学习笔记之】Object.assign()
本文由 微wx笑 创作,采用 署名-非商业性使用-相同方式共享 4.0 许可协议,转载请附上原文出处链接及本声明。
原文链接:https://www.ivu4e.cn/blog/front/2021-01-13/604.html