JavaScript之深浅拷贝

JavaScript之深浅拷贝

了解一下JavaScript中的深浅拷贝,以及他们的手写版

数据类型

首先肯定要知道的是JavaScript的数据类型,JavaScript的数据类型可以分为两大类基本数据类型引用数据类

基本数据类型
  • Number
  • Boolean
  • String
  • Null
  • Undefined
  • Symbol
  • Bigint
引用数据类型
  • Function
  • Object
  • Array

了解完JavaScript拥有的数据类型后,来看看深浅拷贝

浅拷贝

简单的来说就是,基本数据类型完全拷贝他们的数据,引用数据类型就拷贝内存地址

实现
  1. Object.assign()

    var obj = {
    	name: 'ljm',
        age: 18,
        like:{
    		first: "sleep"
        }
    }
    var obj1 = Object.assign({},obj)
    console.log(obj1.name)//ljm
    console.log(obj1.age)//18
    obj1.age = 20
    obj1.like.first = "reading"
    console.log(obj.age)//18
    console.log(obj1.age)//20
    console.log(obj.like.first)//reading
    console.log(obj1.like.first)//reading
    

    这个是Object中的一个内置函数,可以对Object对象中的数据进行浅复制,name和age是obj对象中的基本数据类型,所以浅复制后obj1改变数据不会改变obj的数据,但是like是引用数据类型,只是复制了地址,所以obj2中like改变属性值也会改变obj中like的属性值。

  2. 拓展运算符...

    var obj = {
    	name: 'ljm',
        age: 18,
        like:{
    		first: "sleep"
        }
    }
    var obj1 = {...obj}
    console.log(obj1.name)//ljm
    console.log(obj1.age)//18
    obj1.age = 20
    obj1.like.first = "reading"
    console.log(obj.age)//18
    console.log(obj1.age)//20
    console.log(obj.like.first)//reading
    console.log(obj1.like.first)//reading
    

    拓展运算符是es6中的语法糖,在Object或Array中都可以使用。

  3. Array.prototype.slice

    var arr1 = ["ljm", 18, ["sleep"]];
    var arr2 = arr1.slice(0);
    arr2[1] = 20;
    arr2[2][1] = "reading";
    console.log(arr1[1])//18;
    console.log(arr2[1]);//20
    console.log(arr1[2][1])//reading
    console.log(arr2[2][1])//reading
    
  4. Array.prototype.concat

    var arr1 = ["ljm", 18, ["sleep"]];
    var arr2 = [].concat(arr1)
    arr2[1] = 20;
    arr2[2][1] = "reading";
    console.log(arr1[1])//18;
    console.log(arr2[1]);//20
    console.log(arr1[2][1])//reading
    console.log(arr2[2][1])//reading
    

深拷贝

深拷贝就是不管是基本数据类型还是引用数据类型都重新拷贝一份, 不存在共用数据的现象

实现
  1. JSON.parse(JSON.stringify(obj))

    var obj = {
    	name: 'ljm',
        age: 18,
        like:{
    		first: "sleep"
        }
    }
    var obj1 = JSON.parse(JSON.stringify(obj));
    console.log(obj1.name)//ljm
    console.log(obj1.age)//18
    obj1.age = 20
    obj1.like.first = "reading"
    console.log(obj.age)//18
    console.log(obj1.age)//20
    console.log(obj.like.first)//sleep
    console.log(obj1.like.first)//reading
    

    存在的问题

    1. 会忽略undefined
    2. 会忽略symbol
    3. 不能序列化函数
    4. 不能解决循环引用的对象
    5. 不能正确处理new Date()
    6. 不能处理正则
    7. 不能处理new Error()

    现实中遇到深拷贝的场景很少,而且99%用JSON.stringify可以解决

  2. 递归处理

function deepCopy(obj) {
	  if(obj instanceof Date){
	      return new Date(obj);
	  }else if(obj instanceof Error){
	      return new Error(obj)
	  }else if(obj instanceof RegExp){
	      return new RegExp(obj);
	  }
	  else if(obj instanceof Array){
	      let temp = [];
	      for(let val of obj){
	          temp.push(deepCopy(val));
	          return temp;
	      }
	  }else if(obj instanceof Function){
	      return obj.toString();
	  }else if (obj instanceof Object) { //当拷贝的是对象时
	      let tmp = {}
	      // 递归遍历每一个key值
	      for (let key in obj) {
	          let prop = obj[key];
	          if(prop === obj){ 
	              return obj; //解决循环引用
	          }
	          tmp[key] = deepCopy(obj[key])
	      }
	      return tmp
	  }
	  else{
	      return obj
	  }
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值