浅谈深拷贝和浅拷贝 以及 实际方法

前段时间开发项目中碰到了深浅拷贝的问题,现在给自己写个总结(^▽^)。

简单来说,假设a是引用数据类型,b复制了a,改变a以后,b也跟着改变,就是浅拷贝,b不跟着改变,就是深拷贝。如果要了解具体的运行机制,这篇文章已经讲的很详细了,我也是参考这篇文章写得(^▽^):www.cnblogs.com/echolun/p/7…

什么是引用数据类型?
数据类型分为:基本数据类型引用数据类型
基本数据类型:number,string,boolean,null,undefined五类
引用数据类型:Object类:{a:1},数组:[1,2,3],以及函数等

一.基本数据类型

定义:名、值存储在栈内存中

例子:

var a=1;var b=a; 
a=2; //a=2,b=1
复制代码

注:这里b复制了a,改变a以后,b不跟着改变,但这不是深拷贝。深浅拷贝只是针对较为复杂的引用数据类型来说的。

二.引用数据类型

定义:名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值。

浅拷贝

例子:

var object={a:1,b:2};var copy=object; 
object.a=2; //object={a:2,b:2},copy={a:2,b:2}
复制代码

这里改变了a的值,b也跟着改变,就是浅拷贝

还有一种是半独立状态的浅拷贝,即运行机制还是一样的,只是拷贝了对象实例的属性。

例子:

var a={name:'jack'};var b={...a}; 
a.name='tom' // a={name:'tom'} , b={name:'jack'}
复制代码

等同于

var a={name:'jack'};var b=Object.assign({}, a);
a.name='tom' // a={name:'tom'} , b={name:'jack'}
复制代码

这里通过es6的解构把a拆开赋值给b,这样改变了a的值以后,b还是原来的值,这种就是半独立状态的浅拷贝。

深拷贝

那要怎么实现深拷贝呢?

1.借用JSON对象的parse和stringify方法
let a=[0,1,[2,3],4]
let aClone=JSON.parse(JSON.stringify(a))
a[0]=8;a[2][0]=8; // a=[8,1,[8,3],4],aClone=[0,1,[2,3],4]
复制代码
2.通过递归去复制所有层级属性
deepClone (obj) {
  // 定义需要拷贝的新元素,并判断当前元素是不是数组
  let objClone = Array.isArray(obj) ? [] : {}
  if (obj && typeof obj === 'object') {
    // 判断当前元素是不是对象 or 数组
    for (let key in obj) {
      // 判断obj子元素是否为对象or数组,如果是,递归复制,如果不是,简单复制
      objClone[key] =
        typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
    }
  }
  return objClone
},    
let a = [0,1,2,3];
let b = deepClone(a)
a[0]=8; // a=[8,1,2,3],b=[0,1,2,3]
复制代码
3.依赖JQ库的extend方法
$.extend ( [ deep ], target, object1 [ , objectN ] )
复制代码

deep: 可选。 Boolean类型,指示是否深度合并对象,默认为false。如果该值为true,且多个对象的某个同名属性也都是对象,则该"属性对象"的属性也将进行合并。
target: Object/Array类型的目标对象,其他对象的成员属性将被附加到该对象上。
object1: 可选。 Object/Array类型,第一个被合并的对象。
objectN: 可选。 Object/Array类型,第N个被合并的对象。

let a = {name: 'Jack', age: 13}
let b = {address: 'China'}
let c = JQ.extend(true, [], a, b)
a.name = 'Tom'
console.log(c); // {name: 'Jack', age: 13, address: 'China'}
复制代码
let a = [0, 1, [2, 3], 4]
let b = [123, 456]
let c = JQ.extend(true, [], a, b)
a[2][0] = 8
console.log(c); // [123,456,[2,3],4]
复制代码
4.SessionStorage/LocalStorage

这种方法一般用于全局变量或者刷新时也需要保存的数据,但如果需要保存的数据是object或array类型的,就需要用到JSON.parseJSON.stringify,因为SessionStorage/LocalStorage无法单独获取到存储的数据类型是object或array的。

let arr=[1,2,3]
sessionStorage.setItem('arr', JSON.stringify(arr))
复制代码
JSON.parse(sessionStorage.getItem('arr')); // [1,2,3]
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值