js 深拷贝浅拷贝,以及堆栈存关系

先引用一篇文章JavaScript中的堆栈,作者写得很好。
如果看完上面推荐的文章还没有理解堆栈存与深拷贝浅拷贝的关系,请看?。

引用类型(对象“Object”,数组“Array”,函数“Function”)
引用类型不会在栈内存中保存值,只会在栈内存保存一个指向堆内存的地址。
当引用栈内容的地址的时候,会通过地址查询堆内存的值。
因此就有了浅拷贝深拷贝的区别。
浅拷贝 -> 只是拷贝了栈内存的地址。
深拷贝 -> 生成一个新的堆栈存,拷贝的同时生成一个新的堆内存。

很多人只知道 深拷贝浅拷贝,根本不知道其实现方式,或者说只知道 递归 、JSON.parse(JSON.stringify(obj)) 可以用来实现深拷贝,但并不理解是如何实现的。

我们通过一个数组来说明深拷贝的实现原理。
我们在这里只做一维数组的实现说明(浅显易懂)。对于多维数组的实现就需要通过其他方式 比如 ?递归遍历。

var arr = [1, 2, 3];
// var arr2 = arr; // arr2 只是栈内存的一个地址,当引用时会通过栈内存的地址去查找堆内存中的值

// 通过遍历的方式可以重新分配堆内存,其实就是拿arr的堆内存一个一个赋值给arr2的栈内存的地址。
var arr1 = [];
for (var i = 0; i < arr.length; i++) {
  arr1.push(arr[i]);
}

arr1[1] = 5; // 修改arr1[1] 
console.log(arr, arr1); // [1, 2, 3],[1, 5, 3]// 我们拿arr2来解析,其实也很简单 就是把堆内存重新赋值给另一个引用类型。因此实现深拷贝。
var arr2 = [];
arr2[0] = 1;
arr2[1] = 2;
arr2[2] = 3;

arr2[1] = 4; // 修改arr2[1] 
console.log(arr, arr2); // [1, 2, 3],[1, 4, 3]



对于对象的深拷贝,以及深度优先遍历实现深拷贝方式。
慎用递归,浏览器每次执行代码时,都会分配一定尺寸的栈空间(Windows系统中为1M)。

附上JSON.parse(JSON.stringify(obj)) 的弊端

let func = new (function() {
  this.name = '?';
})();
let objc = {
  a: 1,
  b: function() { // undefined 直接被忽略
    this.name = '?';
  },
  c: NaN, // 转化成 null
  d: new Date(), // 会被转化成字符串
  e: func // 构造函数不拷贝 constructor
};
let A = JSON.parse(JSON.stringify(objc));

console.log(A, objc);


对比

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值