JS中的深浅拷贝以及实现深拷贝的几种方法.

什么是浅拷贝?从基本类型和栈内存以及堆内存讲起.

我们在js中最常用的赋值方式就是浅拷贝.如: 两个对象a,b. 那么 让b等于a.

var b = a;

这就是最基本的浅拷贝了.那浅拷贝的表现形式是什么呢? 解决这个问题我们要先谈谈js中的数据类型了.
在es5中有6中数据类型它们是:undefined,null,Boolean,Stirng,Number,Object.
在es6中新增一个原始的数据类型Symbol那么js就有了7个数据类型了.
但是这些数据类型又可以分为基本数据类型和引用数据类型.

  1. 基本数据类型(undefined,null,Boolean,Stirng,Number):
    如何理解呢?它们保持的变量名(如:a)都标示在栈内存中的实际的值.如 var a = 1; 那么就是说a标示栈内存中的某一值为1的对象.

  2. 引用数据类型(Object):
    引用数据类型与基本数据类型不同点就是在"引用"这两个字上面.它本质上表示在栈内存上的一条指针记录.而指针所指的方向(指到堆内存里面),就是那块堆内存的对象,这才是引用类型真正的值.引用类型栈内存的表现其实就是一条指针记录.

那么究竟什么是浅拷贝呢?

浅拷贝就是栈内存的拷贝. 比如: 我把 a 对象的值赋给 b对象 就是把我a在栈内存里面的内容复制给b了.

var a = b

如果a是基本数据类型.那么b在栈内存里面获得的就是一个和a一样内容的东西(拷贝).他的内容是一个基本类型.

如果a是引用数据类型.那么b在栈内存里面获得的就是一个和a一样内容的东西(拷贝).它的内容是一个指针(指向同一块对内存).!!!(浅拷贝的本质!) 既然b获得是一条与a相同的指针记录.那么a和b本质上都连向同一块堆内存了! 这就是浅拷贝

所以当我们改变b对象中某个属性的值,a中的属性值也随之变化. 因为他们拥有相同的指针.

综上浅拷贝就是说两个对象拷贝的是栈内存中的内容; 基本类型就获得的是对应的值,而引用类型获得的就是指针!!!

指针是导致浅拷贝的表现的根本原因.

什么是浅拷贝的表现. 就是 b 变化了 a也随之变化. 且永远 a===b

代码如下:

let a = {name: 'ldj',age: 30}
let b = a
b.age = 40
console.log(b)
console.log(a)

console.log(a === b)

什么是深拷贝?

通过上面的描述我们知道所谓浅拷贝就是栈内存里面的内容拷贝.而Object类型的话拷贝的就是指针记录(指向同一块对内存). 那深拷贝呢. 就是重新建一块堆内存了,b对象的指针指向这块新的堆内存.a和b指向了不同的堆内存(堆内存里面的属性的值如果是Object类型的话也指向新的堆内存).

深拷贝的方法:

  1. JSON.parse(JSON.stringify(obj)) 方法

let b = JSON.parse(JSON.stringify(a))

其实上面这一轮操作就是让b的指针从新获得一块堆内存了.

  1. 递归递归去复制所有层级属性
function deepClone(obj) {
  if (obj == null) return null;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== 'object') return obj;
  let t = new obj.constructor
  for (let key in obj) {
    t[key] = deepClone(obj[key])
  }
  return t;
}
复制代码

使用递归,每一个层级的去查.如果是引用类型.那就new一个新的对象(new 出来的东西肯定得有一块新的对内存来存储吧.) 然后再把整个新对象return出去.

[误区]还有其他深拷贝的方法了吗?

可能很多朋友认为.

let b = Object.assign({}, a)

或者

let b = {...a, ...{}}

如果a是 Array 类型的值

let b = [].concat(a)

或者

let b = [...a, ...[]]

以上几种方法其实指实现了第一层级的 '深'拷贝. 而没有实现真正意义上的深! 可以这样理解.它只调了deepCloneErr()方法一次 没有去做递归!

第一次写文章,文字差,没配图,请多包涵.

有错误请指正,
有疑问可共同探讨.
谢谢.

转载于:https://juejin.im/post/5b9714b9e51d450ea36304ad

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值