深拷贝和浅拷贝
**在日常开发过程中,我们经常会涉及到数据的拷贝。有时候会有困惑,到底是使用深拷贝还是浅拷贝,
我们先来明确一下什么是深拷贝什么是浅拷贝**
关于对深拷贝和浅拷贝的定义:
浅拷贝
- 如果属性都是基本数据类型,那么就是拷贝基本数据类型的值
- 如果属性里面有引用数据类型,那么拷贝的就是内存地址,这时修改新对象,对导致原对象也被修改了
深拷贝 - 如果属性都是基本数据类型,那么就是拷贝基本数据类型的值
- 如果属性里面有引用数据类型( 对象 ),那么会创建新的对象,将原对象的属性和值拷贝出来,放到新对象里面,并且修改新对象不会对原对象产生影响
/*
使用ES6的展开运算符
*/
const arr = [1,2,3,4]
const obj = {name:"张三",age:12}
const newArr = [...arr]
const newObj = {...obj}
console.log(newArr) // [1, 2, 3, 4]
console.log(newObj) // {name: '张三', age: 12}
Object.assign(目标对象,拷贝源)
/*
Object.assign(target,sources)
第一个参数:目标对象 ( 拷贝到的对象 )
第二个参数:拷贝源 ( 要被拷贝的原对象 )
*/
const obj = { name: '张三', age: 10 }
const arr = [1, 2, 3]
const newObj = Object.assign({}, obj)
const newArr = Object.assign([], arr)
console.log(newObj) // {name: '张三', age: 10}
console.log(newArr) // [1, 2, 3]
使用浅拷贝来拷贝对象里面还有对象的数据时产生的影响
/*
如果对象里面有引用数据类型( 就是对象里面包含了对象 ),使用浅拷贝,
那么修改了拷贝出来的对象,会导致原对象也被修改了
*/
const obj = {
name: '张三',
age: 10,
info: {
address: '湖北',
postcode: '430000',
},
}
const newObj = { ...obj }
// 如果修改了对象里面的引用数据类型的数据,会导致原对象也被修改
newObj.info.postcode = '410000'
console.log(newObj.info) // {address: '湖北', postcode: '410000'
console.log(obj.info)// {address: '湖北', postcode: '410000'}
深拷贝的实现方案 JSON.parse(JSON.stringify(sources))
/*
如果对象里面有引用数据类型( 就是对象里面包含了对象 ),使用深拷贝,
那么修改了拷贝出来的对象,不会导致原对象也被修改了
*/
const obj = {
name: '张三',
age: 10,
info: {
address: '湖北',
postcode: '430000',
},
}const newObj = JSON.parse(JSON.stringify(obj))
newObj.info.postcode = '410000'
console.log(newObj.info) // {address: '湖北', postcode: '410000'}
console.log(obj.info) // {address: '湖北', postcode: '430000'}
使用递归拷贝
// object:要被拷贝的对象hash默认创建一个空map
function deepCopy(object, hash = new Map()) => {
// 判断是否是引用数据类型,如果不是直接返回
if (typeof object != 'object') return object
// 判断 hash里面是否有这个key,如果有也返回
if (hash.get(object)) {
return object
}
// 能执行到这里的只有数组和对象
// object.constructor指向构造函数本身,通过构造函数创建对象或者数组
let container = new object.constructor()
// 向map中存这个key,以后循环的时候如果这个key存在,那么就不在继续循环
hash.set(object, container)
for (let key in object) {
// 如果 object是对象那么,这里的key表示对象的键
// 如果是object是数组,那么key表示数组元素的下标
// 然后这边递归调用,直到object里面没有引用数据类型,那么递归结束
container[key] = deepCopy(object[key], hash)
}
// 最后返回 这个对象或者数组
return container
}const obj = {
name: '张三',
info: {
age: 10,
},
}
const newObj = deepCopy(obj)
newObj.info.age = 20
console.log(newObj.info) // {address: '湖北', postcode: '410000'
console.log(obj.info)// {address: '湖北', postcode: '410000'}
本文内容主要包括:
- 浅拷贝和深拷贝的区别
- 实现浅拷贝的两种方式
- es6的展开运算符
- Object.assign()
- 【JS的深拷贝和浅拷贝的几种实现方案】实现深拷贝的两种方式
- 1: JSON.parse(JSON.stringify)实现深拷贝
- 2: 使用递归函数进行深拷贝