总结一下js中常用的对象、数组拷贝方式。
js中的数据分为基本数据类型和引用数据类型,基本数据类型是直接访问变量对应的值,而引用数据类型是通过读取变量引用地址获取到值。
深浅拷贝是相对于引用类型来说的。
浅拷贝指的是直接将引用类型的引用(对象在内存中的地址)复制给另一个变量,这样改变引用类型的值就都会改变。
深拷贝指的是在内存中新开辟一块内存来存放拷贝的引用类型,也就是指向一个新的内存地址,这样改变引用类型的值不会对另外一个引用类型的值产生影响。
# 浅拷贝
# Object.assign()
const source = { name: 'susan', age: 18, family: { father: 'jenny'} }
const target = Object.assign({}, source)
target.name = '小花'
console.log(source.name) // 小花
console.log(target.name) // 小花
const newTarget = Object.assign({}, source)
newTarget.family.father = 'bob' // 注意 虽然多层的引用类型还是浅拷贝
newTarget.name = 'Lily'
console.log(source.name, source.family.father) // 小花 bob
console.log(newTarget.name, newTarget.family.father) // Lily bob
# concat()
let source = [110, { name: 'susan' }]
let target = source.concat()
target[1].name = '小花'
console.log(source[1].name) //小花
# slice()
const source = [1, { name: 'susan' }]
const target = source.slice()
target[1].name = '小花'
console.log(source) // [1, { name: '小花' }]
console.log(target) // [1, { name: '小花' }]
# 扩展运算符
扩展运算符只是深拷贝了第一层,对深层的引用拷贝还是属于浅拷贝
const source = { name: 'susan', age: 18, family: { father: 'jenny'} }
const target = { ...source }
source.name = '小花'
source.family.father = 'bob'
console.log(source) // 小花
console.log(target) // susan
const sourceArr = [1,2,3, { name: 'susan'} ]
const targetArr = [...sourceArr]
targetArr.push(4)
targetArr[3].name = 'Lily'
console.log(sourceArr) // [1,2,3, { name: 'Lily' }]
console.log(targetArr) // [1,2,3, { name: 'Lily' }, 4]
# 深拷贝
# JSON.parse(JSON.stringify())
对正则、函数、date等无法正确地拷贝
const source = [1, { name: 'susan'}]
const target = JSON.parse(JSON.stringify(source))
# 递归遍历
// 判断类型
function getType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
}
// 递归遍历拷贝
function copy(target) {
let result, targetType = getType(target)
if(targetType === 'Object') {
result = {}
} else if(targetType === 'Array') {
result = []
} else {
return target
}
// 遍历
for(let i in target) {
let val = target[i]
if(getType(val) === 'Object' || getType(val) === 'Array') {
result[i] = copy(val)
} else {
result[i] = val
}
}
return result
}