js 实现对象的拷贝、深拷贝
微wx笑 2021-01-13【前端开发】 3 0关键字: js 对象 拷贝 深拷贝 复制 vue
在使用vue等响应式框架的时候,为了让框架能够监测到数据的改变,我们经常会用到对象的拷贝功能。这里收集了一些实现的方法及注意事项。Object.assign() 基本用法Object.assign
在使用vue等响应式框架的时候,为了让框架能够监测到数据的改变,我们经常会用到对象的拷贝功能。这里收集了一些实现的方法及注意事项。
Object.assign()
基本用法
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
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方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
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
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数据这样的键值对有效
对于函数等等反而无效,不好用,接着继续看方法二、三。
方法二
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: '母' } ] }
方法三
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)
方法四
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