赋值、浅拷贝与深拷贝

简介: 赋值、浅拷贝与深拷贝

前面我们讲过,基本数据类型存放的栈中,引用数据类型存放在堆中,指向引用数据类型的变量保存在栈中,它保存着指向堆中对应引用数据类型的内存地址(对以上问题不了解的朋友可以查看之前的一篇文章《JavaScript之内存空间》),由此看如下代码:


let a = 'a';
let b = a;
let obj1 = {
  name:'obj1.name'
}
let obj2 = obj1;
复制代码


首先声明了变量a并赋值'a',然后声明b = a,这个时候属于赋值,即创建变量b,并赋值'a';


接下来声明对象obj1并赋值,此时在内存中创建了对象{name:'obj1.name'},然后声明obj2 = obj1,


这个时候只是把obj1中保存的指向对象{name:'obj1.name'}的内存地址赋给了obj2,并不会再创建一个对象{name:'obj1.name'}


那么接下来看如下代码:


let xm = {
  name:'小明',
  hobby:['足球','篮球']
}
let xz = xm;
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
xz.name = '小张';
console.log(xm);
// {
//   name:'小张',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小张',
//   hobby:['足球','篮球']
// }
复制代码


因为let xz = xm只是把xm保存的对象的内存地址赋给了xz,所以当通过xz.name = '小张'改变了这个对象的时候,打印xm和xz拿到的都是改变后的对象,那么如何复制一个对象呢?


可能你会想到Object.assign()


**Object.assign()** 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。  ---- (MDN)


那我们修改上面的代码如下:


let xm = {
  name:'小明',
  hobby:['足球','篮球']
}
let xz = Object.assign({},xm);
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
xz.name = '小张';
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小张',
//   hobby:['足球','篮球']
// }
复制代码


可能你会觉得还不错嘛,那我们再修改一下:


let xm = {
  name:'小明',
  hobby:['足球','篮球']
}
let xz = Object.assign({},xm);
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
xz.name = '小张';
xz.hobby.push('乒乓球');
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球','乒乓球']
// }
console.log(xz);
// {
//   name:'小张',
//   hobby:['足球','篮球','乒乓球']
// }
复制代码


你会发现,不对啊,我明明只想给xz添加爱好,xm的爱好怎么也多了?


下面我们正式引出浅拷贝和深拷贝


浅拷贝


其实浅拷贝就像我们上面说的变量赋值,当对象的属性值为基本数据类型,那么拷贝的就是基本数据类型的值,如果对象的属性值为引用数据类型,那么拷贝的就是内存地址,上面的代码可以用下图更形象的解释:


网络异常,图片无法展示
|


所以,类似于Object.assign()属于浅拷贝


深拷贝


理解了浅拷贝,深拷贝的概念就呼之欲出了,所谓深拷贝,即不管对象的属性是基本数据类型还是引用数据类型,都会进行拷贝,所以拷贝前后的两个对象是相互独立,互不影响的。


上面例子实现深拷贝代码如下:


let xm = {
  name:'小明',
  hobby:['足球','篮球']
}
let xz = JSON.parse(JSON.stringify(xm));
xz.name = '小张';
xz.hobby.push('乒乓球');
console.log(xm);
// {
//   name:'小明',
//   hobby:['足球','篮球']
// }
console.log(xz);
// {
//   name:'小张',
//   hobby:['足球','篮球','乒乓球']
// }
复制代码


JSON.parse(JSON.stringify(obj))存在以下几个问题:


let obj1 = {
  name:'obj',
  a:undefined,
  b:/\d{6}/g,
  c:function(){
    console.log(this)
  },
  d:new Date(),
  s:Symbol(123)
}
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2);
// {
//   name: "obj",
//   b: {},
//   d: "2019-03-26T13:51:45.158Z"
// }
复制代码


可见对于undefined,函数,Symbol会直接忽略


对于new Date()转换后结果不正确


对于正则转换为{}


再看一种情况:


let obj1 = {
  a:{name:'a'}
}
obj1.b = obj1.a;
obj1.b.c = obj1.a;
console.log(obj1);
let obj2 = (JSON.parse(JSON.stringify(obj1)));
console.log(obj2);
// Uncaught TypeError: Converting circular structure to JSON
复制代码


可见对于循环引用,会报错。


如果有错误或者不严谨的地方,请给予指正,十分感谢!


相关文章
|
1月前
|
存储 前端开发 JavaScript
浅拷贝和深拷贝的区别?
本文首发于微信公众号“前端徐徐”,介绍了JavaScript中浅拷贝和深拷贝的概念及其实现方法。文章首先解释了数据类型的基础,包括原始值和对象的区别,然后详细介绍了浅拷贝和深拷贝的定义、底层逻辑以及常见的实现方式,如 `Object.assign`、扩展运算符、`JSON.stringify` 和手动实现等。最后,通过对比浅拷贝和深拷贝的区别,帮助读者更好地理解和应用这两种拷贝方式。
52 0
浅拷贝和深拷贝的区别?
|
5月前
|
安全 Java
深拷贝和浅拷贝的区别
深拷贝和浅拷贝的区别
|
4月前
|
编译器 C++
深拷贝和浅拷贝介绍
这篇文章讨论了C++中的数据拷贝,特别是浅拷贝和深拷贝的概念。对于基本类型和简单对象,拷贝是按位复制,即浅拷贝,类似于`memcpy()`函数的效果。当类包含动态分配的内存或其他资源时,需要显式定义拷贝构造函数以实现深拷贝,确保对象间的独立性。文中通过一个自定义的变长数组类`Array`示例说明了深拷贝的必要性,并展示了不使用深拷贝可能导致的问题。通常,如果类有指针成员,大部分情况需要深拷贝;否则,浅拷贝可能就足够了。文章还提到了在创建对象时需要预处理的情况,如记录对象创建时间或计数,这也需要深拷贝。
|
6月前
|
消息中间件 Kubernetes NoSQL
构造函数、深拷贝、浅拷贝
构造函数、深拷贝、浅拷贝
|
编译器 C++
C++中的深拷贝和浅拷贝介绍
对于基本类型的数据以及简单的对象,它们之间的拷贝非常简单,就是按位复制内存。例如: class Base{ public: Base(): m_a(0), m_b(0){ } Base(int a, int b): m_a(a), m_b(b){ } private: int m_a; int m_b; }; int main(){ int a = 10; int b = a; //拷贝 Base obj1(10, 20);
124 0
|
Java
浅拷贝与深拷贝
浅拷贝与深拷贝
86 0
|
JSON 数据格式
深拷贝和浅拷贝、及实现方式
深拷贝和浅拷贝、及实现方式
95 0
|
JSON JavaScript 数据格式
js对象的直接赋值、浅拷贝与深拷贝
js对象的直接赋值、浅拷贝与深拷贝
145 0
js对象的直接赋值、浅拷贝与深拷贝
|
JavaScript 前端开发
数组和对象的浅拷贝,深拷贝
数组和对象的浅拷贝,深拷贝
数组和对象的浅拷贝,深拷贝