在 JavaScript 中,对象的拷贝可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。理解这两者的区别是非常重要的,因为它们影响着拷贝后的对象与原始对象之间的关系。
- 浅拷贝(Shallow Copy):
浅拷贝只会拷贝对象的第一层属性。如果对象的属性是基本数据类型(例如,字符串,数字,布尔值等),那么拷贝的就是基本数据类型的值。但如果属性是引用数据类型(例如,对象,数组等),拷贝的就是这个属性在内存中的地址,而不是真正的内容。这就意味着,如果修改了这个拷贝后的对象中的引用类型属性,那么原始对象也会被改变。
JavaScript 中实现浅拷贝的方法有很多种,例如使用 Object.assign()
或者展开运算符 ...
。
const obj = { a: 1, b: 2, c: { d: 3 } };
const shallowCopy = { ...obj };
shallowCopy.c.d = 4;
console.log(obj); // { a: 1, b: 2, c: { d: 4 } }
console.log(shallowCopy); // { a: 1, b: 2, c: { d: 4 } }
你可以看到,虽然我们修改了 shallowCopy
对象的 c.d
属性,但原始对象 obj
的相应属性也被改变了,这就是浅拷贝的特性。
- 深拷贝(Deep Copy):
深拷贝会拷贝对象的所有层级,包括它的所有子对象和子数组等。这意味着,对于对象的任何属性,无论是基本数据类型还是引用数据类型,都会被完全复制一份,形成一份全新的对象。这样,无论怎么修改新对象,都不会影响到原始对象。
在 JavaScript 中,可以通过一些方法实现深拷贝,例如 JSON.parse(JSON.stringify(object))
(注意,这个方法有局限性,无法处理函数、undefined、循环引用等)。此外,还有一些库,如 lodash 的 _.cloneDeep()
方法,也可以实现深拷贝。
const obj = { a: 1, b: 2, c: { d: 3 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.c.d = 4;
console.log(obj); // { a: 1, b: 2, c: { d: 3 } }
console.log(deepCopy); // { a: 1, b: 2, c: { d: 4 } }
在这个例子中,你可以看到,虽然我们修改了 deepCopy
对象的 c.d
属性,但原始对象 obj
的相应属性并未被改变,这就是深拷贝的特性。
两者的区别
浅拷贝与深拷贝之间的区别主要体现在对对象内部引用类型的处理方式上,以及拷贝后新对象与原始对象之间的独立性。以下是两者之间的详细区别:
浅拷贝(Shallow Copy)
-
引用类型共享:浅拷贝仅复制对象的顶层属性。如果对象的属性值是基本类型(如数字、字符串、布尔值等),则直接复制该值。但如果属性值是引用类型(如对象、数组、函数等),则复制的是内存地址的引用,而不是实际的对象。因此,原始对象和拷贝后的对象会共享同一个引用类型的实例。
-
修改影响原始对象:由于引用类型的共享,如果对拷贝后的对象中的引用类型属性进行修改,这些修改也会反映到原始对象中。这是因为两者都指向同一个内存地址。
-
性能开销较小:浅拷贝通常比深拷贝更快,因为它不需要递归地复制对象的所有层级。
-
实现方式:在 JavaScript 中,可以使用
Object.assign()
方法、展开运算符(...
)或数组的slice()
、concat()
方法等来实现浅拷贝。
深拷贝(Deep Copy)
-
完全独立:深拷贝会递归地复制对象的所有层级,包括所有的子对象和子数组。这意味着拷贝后的对象是一个完全独立的实例,与原始对象没有任何关联。
-
修改不影响原始对象:由于深拷贝创建了对象的完整副本,包括所有引用类型的属性,因此对拷贝后的对象进行的任何修改都不会影响原始对象。
-
性能开销较大:深拷贝通常比浅拷贝更慢且更消耗内存,因为它需要递归地复制对象的所有层级和属性。
-
实现方式:在 JavaScript 中,可以使用
JSON.parse(JSON.stringify(object))
(有局限性,无法处理函数、undefined、循环引用等)或第三方库(如 lodash 的_.cloneDeep()
方法)来实现深拷贝。 -
处理循环引用:深拷贝的一个挑战是处理对象之间的循环引用。如果对象之间存在循环引用,简单的递归复制可能会导致无限循环。因此,实现深拷贝的库通常需要具备检测和处理循环引用的能力。
综上所述,浅拷贝和深拷贝的主要区别在于它们对引用类型属性的处理方式以及拷贝后新对象与原始对象之间的独立性。选择使用哪种拷贝方式取决于具体的应用场景和需求。
标签:obj,对象,JavaScript,引用,拷贝,Copy,属性 From: https://blog.csdn.net/qq_43536788/article/details/136841266