深拷贝浅拷贝学习

目标

1.什么是深拷贝
2.实现方式
3.在vue中的使用

前置知识

js的一般数据类型存储 number string boolean undefined null
js的引用类型存储  obj

浅拷贝 深拷贝

浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝,如果属性是基本类型拷贝的就是基本类型的值如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

深拷贝是将一个对象从另一个对象中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

针对引用类型来说 赋值 深拷贝 浅拷贝区别

1.浅拷贝赋值的区别
tips:赋值指的是同一个地址
let person= {
name:1
}
let person1 = person 都公用的是{}内容
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象在栈中的地址,而不是堆中的数据。也就是两个对象指向的同一个存储空间,无论哪个对象发生改变其实都是改变的存储空间的内容,因此两个对象是联动的
浅拷贝:重新在队中创建内存,拷贝前后数据互不影响,但拷贝前后对象的引用类型因共享同一块内存会相互影响。
深拷贝:从堆内存中开辟了一个新的区域存放新对象,对对象中的而对象进行递归拷贝,拷贝前后的两个都西互不影响

var a = 123//普通数据类型存储在栈中,引用类型保存在堆中
var obj = {} //var 一个obj这个变量是存储在栈里面的。{}请添加图片描述
这就是赋值图的解释
在这里插入图片描述
var person1 = person;赋值

这就是浅拷贝从新指了个地址。
浅拷贝虽然指了个地址,然如果数据是基本类型的话会互不影响,如果是引用类型就会影响
在这里插入图片描述
//浅拷贝

var person = {
		name:'张三',
		hobby:['学习',['看电影','玩'],'跑步']
   }
function shallCopy(obj){
	var target = {}
	for(var i in obj){
		if(obj.hasOwnProperty){
			target[i] = obj[i]
		}
	}
	return target
}
var person1 = shallCopy(person)

//深拷贝

function deepClone(obj){
// var cloneObj = {}
var cloneObj = new obj.constructor() //逼格高
if(obj === null) return obj
if(obj instanceof Date) return new Date(obj)
if(obj instanceof RegExp) return new RegExp(obj)
if(typeof obj !== 'object') return obj
for(var i in obj){
	if(obj.hasOwnProperty(i)){
		cloneObj[i] = deepClone(obj[i])
	}
}
return cloneObj
}
var person1 = deepClone(person)
person1.name = '李四'
person1.hobby[0] = '吃鸡'
console.log(person);
console.log(person1);

浅拷贝的实现方式

Object.assign()
lodash 里面的 _.clone
…展开运算符
Array.propotype.concat
Array.propotype.slice

##深拷贝的实现方式
JSON.parse(JSON.stringify())
递归操作
lodash 里面的 cloneDeep
Jquery.ectend()

JSON.parse(JSON.stringify())的缺点

参考
JSON.parse(JSON.stringify(obj))实现深拷贝的弊端以及解决方法
浅拷贝 : 只是将数据中所有的数据引用下来,依旧指向同一个存放地址,拷贝之后的数据修改之后,也会影响到原数据的中的对象数据。例如:Object.assign(),…扩展运算符

深拷贝: 将数据中所有的数据拷贝下来,对拷贝之后的数据进行修改不会影响到原数据。。

JSON.parse(JSON.stringify(obj))深拷贝的问题

const newState = Object.assign({}, state)和JSON.parse(JSON.stringify(obj))都是可以用来深拷贝 但是也会出现下面的问题
1.如果obj里面存在时间对象,JSON.parse(JSON.stringify(obj))之后,时间对象变成了字符串。
2.如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象。
3.如果obj里有函数,undefined,则序列化的结果会把函数, undefined丢失。
4.如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null。
5.JSON.stringify()只能序列化对象的可枚举的自有属性。如果obj中的对象是有构造函数生成的,则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor。
6.如果对象中存在循环引用的情况也无法正确实现深拷贝。

function Person (name) {
    this.name = 20
}

const lili = new Person('lili')

let a = {
    data0: '1',
    date1: [new Date('2020-03-01'), new Date('2020-03-05')],
    data2: new RegExp('\\w+'),
    data3: new Error('1'),
    data4: undefined,
    data5: function () {
    	console.log(1)
    },
    data6: NaN,
    data7: lili
}
// 合并对象  
//   const newState = Object.assign({}, state)
// 先石化  再解封  就重新开辟空间了   
let b = JSON.parse(JSON.stringify(a))

在这里插入图片描述
解决方法:

//lodash 
//  这个库  解决了 javascript中的 疑难杂症  比如深拷贝  npm  insall loadsh 
 //const { cloneDeep } = require('lodash')

总结
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值