JavaScript:利用递归实现对象深拷贝
先来普及一下深拷贝和浅拷贝的区别
浅拷贝:就是简单的复制,用等号即可完成
let a = {a: 1}
let b = a
这就完成了一个浅拷贝
但是当修改对象b的时候,我们发现对象a的值也被改变了
b.a = 10
console.log(a.a) => 10
这是因为浅拷贝只复制了指向对象的指针,新旧对象共用同一块内存,修改某一个对象的同时也会把另一个都一并修改了
深拷贝:跟浅拷贝最简单明了的区别就是修改拷贝的对象,不会改变源对象
利用Object.assign可以对只有一层的对象实现深拷贝,如下:
let a = {a: 1,b: 2,c: 3}
let b = Object.assign({}, a)
b.b = 100
console.log(a.b) => 2
可以看出来这样是完全可以做到对只有一层的对象实现深拷贝的
但是如果对象里面的元素还是对象的话就没作用了
let a = {a: 1,b: 2,c: 3, d: {a: 1}}
let b = Object.assign({}, a)
b.d.a = 100
console.log(a.d.a) => 100
对于这种比较复杂的对象,我们就可以利用递归的方式实现真正的对象深拷贝了
function deepClone (sourceObj, targetObj) {
let cloneObj = targetObj || {}
if(!sourceObj || typeof sourceObj !== "object" || sourceObj.length === undefined){
return sourceObj
}
if(sourceObj instanceof Array){
cloneObj = sourceObj.concat()
} else {
for(let i in sourceObj){
if (typeof sourceObj[i] === 'object') {
cloneObj[i] = deepClone(sourceObj[i], {})
} else {
cloneObj[i] = sourceObj[i]
}
}
}
return cloneObj
}
简单的几行代码就可以轻松实现对象的深拷贝
简单的测试代码,如下:
let sourceObj = {
a: 1,
b: {
a: 1
},
c: {
a: 1,
b: {
a: 1
}
},
d: function() {
console.log('hello world')
},
e: [1, 2, 3]
}
let targetObj = deepClone(sourceObj, {})
targetObj.c.b.a = 9
console.log(sourceObj) => { a: 1, b: { a: 1 }, c: { a: 1, b: { a: 1 } }, d: [Function: d], e: [ 1, 2, 3 ] }
console.log(targetObj) => { a: 1, b: { a: 1 }, c: { a: 1, b: { a: 9 } }, d: [Function: d], e: [ 1, 2, 3 ] }
另外介绍两个用来做深拷贝的库
**jquery**
使用方法:
let targetObj = $.extent(true,{},sourceObj)
**lodash函数库**
使用方法:
npm install lodash
**es5写法**
let lodash = require('lodash')
**es6写法**
import lodash from 'lodash'
let targetOj = lodash.cloneDeep(sourceObj)