深拷贝和浅拷贝 javascript
一、深拷贝和浅拷贝的原因
- 深拷贝和浅拷贝主要是针对于引用类型数据而言的,深拷贝开辟一块新的空间给赋值后的变量,这样二者不会互相影响。
- js数据类型主要分为基本数据类型和引用数据类型,基本数据类型有:Number,String,Boolean,Symbol,Null,Undefined;引用数据类型有:Object,Array,Function。
- 基本数据类型是将数据直接存储在栈中的,而引用数据类型是将指针地址存储在栈中,将引用类型的数据存储在堆中,赋值也只是将栈中的内容赋值,因此引用类型赋值只是将栈中的指针地址赋值给另一个变量,没有开辟一个新的空间存储,赋值后的引用类型和原引用类型指向同一个地址,修改其中任何一个的数据会影响另一个的数据。
二、例子
例子中使用的数组和对象:
let arr = [{
id: '1',
name: '数组'
}]
let obj = {
id: '1212',
name: '第一层',
objs: {
name: '第二层'
}
}
- 数组和对象深拷贝:JSON.parse(JSON.stringify())
let copyArr = JSON.parse(JSON.stringify(arr));
let copyObj = JSON.parse(JSON.stringify(obj));
arr[0].name = '修改数组'
obj.name = '修改第一层'
obj.objs.name = '修改第二层'
console.log(copyArr)
console.log(copyObj)
结果(深拷贝的数据不会有变化,不管对象或数组有多少层,二者互相不影响):
- 对象浅拷贝 ,只能保证对象第一层数据不改变,第二层数据或者更深入的数据会改变,使用
Object.asign()
和扩展运算符...
let copyObj = Object.assign({}, obj)
let copyObjTwo = {...obj}
obj.name = '修改第一层'
obj.objs.name = '修改第二层'
console.log(copyObj)
console.log(copyObjTwo)
结果(第一层数据不会改变,第二层数据改变了):
- 数组浅拷贝,只能保证数组第一层数据不改变,第二层数据或者更深入的数据会改变,使用数组的
slice()
方法,数组也可以用扩展运算符...
,结果和对象是一样。
let arrAnother = ['javascript', 'java', 'C语言'] // 数组只用一层数据
let copyArr = arr.slice(0) // arr是嵌套对象的
let copyArrAnother = arrAnother.slice(0)
arr[0].name = '修改二层数组'
arrAnother[0] = '修改一层数组'
console.log(copyArr)
console.log(copyArrAnother)
结果(第一层数据不会改变,第二层数据改变了):
还有,深拷贝还可以使用递归来处理,因为JSON.parse(JSON.stringify())这种方法对于数组或对象属性是undefined和function等不可枚举的数据类型无法序列化。
拜拜