深拷贝浅拷贝,原型,类型校验,递归深拷贝

遇见一个问题,解决的时候衍生出了几条底层原理。为此做一下总结

let arr = ['1', '2', '3', {
    name: 'zhangsan'
}, {
    name: 'lisi'
}]

声明一个数组,要求对数组进行深拷贝
一 、 深拷贝和浅拷贝的区别
所有基础数据类型(String,Number,null,undefind,Boolean)进行赋值时都是深拷贝
所有声明的变量在赋值引用数据类型时,都是浅拷贝,因为引用数据类型都是存放在堆中,而声明的变量就相当于一个指针,指向了堆中的数据,所以在进行赋值的时相当于只复制了指针。当堆中的数据发生改变,指向数据的变量也会发生改变。
而深拷贝就相当于把存放在堆中的数据拿出来在存储一份。

常用实现深拷贝的方法有

转换成JSON字符串,再将其转换回来

 let newarr = JSON.parse(JSON.stringfiy(arr))

递归的方法实现深拷贝

 Object.prototype.copy = function (arr) {
       if (typeof arr === 'object') {
           let newarr = Object.prototype.toString.call(arr).slice(8,-1) == "Array" ? [] : {} 
           for(let key in arr){
               newarr[key] = typeof(arr[key]) === 'object' ? copy(arr[key]) : arr[key]
           }
           return newarr
       } else {
          return arr
       }
   }
   let arr2 = copy(arr)
   arr[4].name = "王五"
   console.log(arr,arr2);

创建一个copy( )方法放在Object的原型上
这里放张图片解释下原型之间的关系
原型之间的关系
进入递归后首先判断传递进来的数据的数据类型,判断数据类型的方法有
1、 typeof 判断基础数据类型,返回一个字符串。无法判断引用数据类型,因为万物皆对象,所以在使用typeof 判断数组的时候也会返回object
2、instanceof 可以用来判断引用数据类型

// 例如 判断arr 是否为数组
console.log(arr instanceof Array)    // 返回true   //返回boolean类型的值,true或者false
console.log(obj instanceof Array)  //返回false
//但是当判断arr 是否为对象时,会返回true,因为数组也是特殊的对象
 console.log(arr instanceof Object)  //返回true

3、通过原型的construtor属性判断数据类型
在这里插入图片描述
在这里插入图片描述
理应constructor方法可以解决问题了,但是因为undefined和null没有constructor,所以是不能够判断出类型的,并且会报错
4、Object.prototype.toString.call() 完美解决问题

最后对递归实现深拷贝做下解释

 Object.prototype.copy = function (arr) {
 		//判断传递进来的数据类型,如果不是数组或者对象,
       if (typeof arr === 'object') {
       	//声明变量,如果arr是数组就 赋值 [],对象就赋值{}
           let newarr = Object.prototype.toString.call(arr).slice(8,-1) == "Array" ? [] : {} 
           //循环arr
           for(let key in arr){
           	// 将arr对应的key值,赋值给newarr时判断,如果key值也是对象或数组,再次调用函数递归
               newarr[key] = typeof(arr[key]) === 'object' ? copy(arr[key]) : arr[key]
           }
           return newarr
       } else {   //直接 return
          return arr
       }
   }
   let arr2 = copy(arr)
   arr[4].name = "王五"
   console.log(arr,arr2);

以上

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值