深拷贝与浅拷贝
-
一般数据类型存储
var a = 1
Number String Boolean Symbol null undefined
-
引用数据类型
var obj = {}
object function array date
/**
{} 会保存在堆内存中
ojb 会保存在栈内存中 obj 的指向为 {} obj ---- > {}
*/
深拷贝 浅拷贝 赋值
- 浅拷贝:创建一个新对象 拷贝当前对象的原始属性 如果属性是基本类型 拷贝的是基本类型的值 如果是引用类型则拷贝的是引用类型的内存地址 如果其他对象更改了其内存地址 则会影响到另个对象
- 深拷贝:是从内存中完整拷贝出改对象 然后再内存中新开辟一个空间来存储 拷贝两者之间地址没有关联 更改地址后 不会影响改对象
var a = 123
var obj = {}
var father = {
name:'zhangs',
play:['a',{cat:'mao'},4]
}
var son = father
son.name = 1
son.play[0] = 'c'
// log(son , father) {name:1,play:['c',{cat:'mao'},4]}
-
引用类型的赋值是对象引用
因为内存地址指向同一个地方 则改变改堆内存数据后 son 和 father 的值都会更改
graph LR;
栈内存---堆内存;
son赋值-->obj;
father赋值-->obj
graph LR;
father浅拷贝-->obj基本数据类型;
son浅拷贝-->obj1基本数据类型;
graph LR;
father浅拷贝-->obj引入数据类型;
son浅拷贝-->obj引入数据类型;
浅拷贝 赋值 深拷贝 区别
- 赋值:指向的是栈内存的地址 就是指向的栈内存的地址 而不是堆内存的数据 可以理解为两个对象指向了同一个堆内存 这样 无论哪个对象发生改变 都会影响堆内存的数据 而改变另一个对象
- 浅拷贝:是重新在堆内存中新建一个内存 对对象里面的数据进行递归拷贝 拷贝后的基本数据类型互不影响 拷贝后的引入数据类型 因为指向的都是同一个堆内存,所以会互相影响
- 深拷贝:从堆内存新开辟一块内存来存放新对象 拷贝前后堆 栈 内存都互不影响
var father = {
name:'zhangs',
play:['a',{cat:'mao'},4]
}
// 浅拷贝
function copy(obj){
let obj1 = {}
for(var k in obj){
if(obj.hasOwnProperty(k)){
obj1[k] = obj[k]
}
}
return obj1
}
var son = copy(father)
son.name = 'lis'
son.play[0]= 'c'
//log son father
// { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] }
// { name: 'zhangs', play: [ 'c', { cat: 'mao' }, 4 ] }
/*基本数据类型不会相互影响 但是引用数据类型会相互影响 */
// 深拷贝
function deepCopy(obj){
var obj1 = new obj.constructor()
// 递归需要有出口
if(obj === null) return obj
if (typeof obj !== 'object') return obj
if(obj instanceof Date) return new Date(obj)
if(obj instanceof RegExp) return new RegExp(obj)
for(var k in obj){
if(obj.hasOwnProperty(k)){
obj1[k] = deepCopy(obj[k])
}
}
return obj1
}
var son = deepCopy(father)
son.name = 'lis'
son.play[0] = 'c'
console.log(son,father)
//log { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] }
// { name: 'zhangs', play: [ 'a', { cat: 'mao' }, 4 ] }
-
使用JSON来进行深拷贝
json.parse() 对于 function date 等不能转换 会导致为空
var father = { name:'zhangs', play:['a',{cat:'mao'},4] } // 深拷贝 function deepCopy(obj){ return JSON.stringify(obj) } var son = JSON.parse(deepCopy(father)) son.name = 'lis' son.play[0] = 'c' console.log(son,father) //log { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] } // { name: 'zhangs', play: [ 'a', { cat: 'mao' }, 4 ] }\