理解深浅拷贝

理解前端JS深浅拷贝

前置知识:

  • JS的一般数据类型的存储(stirng number boolean undefinded null)
  • JS的引用数据类型的存储(Object)

浅拷贝 深拷贝

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

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

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

  • 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是说两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

    var person = {
    			name:'爱就一个字',
    			hobby:['学习',['看电影','购物'],'跑步']
    		}
    		//赋值 实现
    
    		var person1 = person
    		person1.name = '艾灸两个字'
    		person1.hobby[0] = '玩耍'
    
    		console.log(person)   
    		console.log(person1)   // 显示结果: 两个person 对象完全一致
    
  • 浅拷贝:重新在堆中创建内存,拷贝前后基本数据类型互不影响,但拷贝前后对象的引用数据类型共享同一块数据内存,会相互影响。

    		var person = {
    			name:'爱就一个字',
    			hobby:['学习',['看电影','购物'],'跑步']
    		}
    	// 浅拷贝的实现
    		function ShallowCopy(obj){
    			var target = {}
    			for(var i in obj){
    				if(obj.hasOwnProperty(i))){
    					target[i] = obj[i]
    				}
    			}
    			return target
    			}
    
    
    		var person1 = ShallowCopy(person)
    		 person1.name = '艾灸两个字'
    		 person1.hobby[0] = '玩耍'
    
    			console.log(person) // person 的 name属性属于 基本数据类型所以没有改变
    			console.log(person1)// person1 的 hobby数组里面内容和 person 一致 都为改变后的内容
    
  • 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后两个对象互不影响。

    	function deepClone(obj){
    			var cloneObj = {}
    			if(obj === null) return obj // null 的 type 是 object类型 (JS的历史遗留问题)
    			if(obj instanceof Date) return new Date(obj) // Date 的 PrototypeOf 是否在 obj 上
    			if(obj instanceof RegExp) return new RegExp(obj) // RegExp 的 PrototypeOf 是否在 obj 上
    			if(typeof obj !== 'object') return obj  // 递归结束出口
    			for(var i in obj){
    				if(obj.hasOwnProperty(i)){
    					cloneObj[i] = deepClone(obj[i]) // 只要是 object 类型就一直递归
    				}
    			}
    			return cloneObj
    		}
    
    		var person1 = deepClone(person)
    		 person1.name = '艾灸两个字'
    		 person1.hobby[0] = '玩耍'
    
    			console.log(person) // person 保持不变
    			console.log(person1)// person1 保持改变后的样子
    

    浅拷贝的实现方式

    • Object.assign( )

      var obj = {} // 存储在栈里面 指向 堆  
      
      		var person = {
      			name:'爱就一个字',
      			hobby:['学习',['看电影','购物'],'跑步']
      		}
      
      		Object.assign(obj,person)
      		obj.name = '111'
      		obj.hobby[0] = '学个P'
      		console.log(person)
      		console.log(obj)
      
  • lodash 里面的 _.clone( ) 一个Js的原生库 里面封装的这个方法可以实现浅拷贝

  • …展开运算符

  • 	var obj = {} // 存储在栈里面 指向 堆  
    		var person = {
    			name:'爱就一个字',
    			hobby:['学习',['看电影','购物'],'跑步']
    		}
    		obj = {...person}
    		obj.name = '111'
    		obj.hobby[0] = '学个P'
    		console.log(person)
    		console.log(obj)
    
  • Array.prototype.concat

    const arr = [1,2,{name:'tony'}]
    			const newArr = arr.concat()
    			newArr[1] = 5
    			newArr[2].name = 'Tom'
    			console.log(arr)
    			console.log(newArr) 
    
  • Array.prototype.slice

    const arr = [1,2,{name:'tony'}]
    			const newArr = arr.slice()
    			newArr[1] = 5
    			newArr[2].name = 'Tom'
    			console.log(arr)
    			console.log(newArr) 
    

    深拷贝的实现方式

  • JSON.parse(JSON.stringify())

    // 使用JSON.parse实现深拷贝  缺点:不完善  Date  RegExp function 类型有问题
    	var person1 = JSON.parse(JSON.stringfy(person))
    
  • 递归的操作

  • Jquery中的$.extend( )方法

  • lodash里的_.cloneDeep( )方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值