您当前的位置:首页 > 计算机 > 编程开发 > JavaScript

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

时间:01-07来源:作者:点击数:
先引用一篇文章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);

对比

在这里插入图片描述
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐