js中深拷贝与浅拷贝在JavaScript开发中,对象拷贝是一个基础但至关重要的概念,尤其当我们需要在不修改原始数据的情
在JavaScript开发中,对象拷贝是一个基础但至关重要的概念,尤其当我们需要在不修改原始数据的情况下,对数据进行操作或传递时。对象拷贝分为浅拷贝和深拷贝两种,它们各有千秋,适用于不同的场景。
浅拷贝:表层的复制
浅拷贝仅复制对象的顶层属性,对于基本类型(如字符串、数字、布尔值)直接复制值,而对于引用类型(如对象、数组),它复制的是引用而非值本身。这意味着,虽然你得到了一个“新”对象,但其中的引用类型属性仍然指向同一个内存地址,因此修改任何一个对象都可能影响到另一个。
浅拷贝的实现方式
Object.assign()
Object.assign()
方法可以用来浅拷贝对象。它接受一个目标对象和一个或多个源对象,然后将源对象的所有可枚举属性的值复制到目标对象。这使得我们可以很容易地创建一个浅拷贝。
const source = { name: '小红', age: 25 };
const shallowCopy = Object.assign({}, source);
- 扩展运算符(
...
)
扩展运算符可以用来创建一个对象或数组的浅拷贝。它将一个对象或数组的元素解构并复制到新的实例中。
const source = { name: '小红', age: 25 };
const shallowCopy = { ...source };
Array.prototype.slice()
(适用于数组)
数组的 slice()
和 concat()
方法都可以用来创建一个数组的浅拷贝。
const array = [1, 2, 3];
const shallowCopy = array.slice();
深拷贝:彻底的复制
深拷贝则是创建一个全新的对象,它不仅复制顶层属性,还会递归地复制所有层级的属性,包括引用类型,确保新对象与原对象完全独立,互不影响。
深拷贝的实现方式
- 递归实现
通过递归遍历对象的属性,我们可以实现一个深拷贝的功能。对于每个属性,如果是引用类型,就再次调用深拷贝函数;如果不是,就直接复制其值。
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
let result = Array.isArray(obj) ? [] : {};
for (let key of Object.keys(obj)) {
result[key] = deepCopy(obj[key]);
}
return result;
}
-
JSON.stringify()
和JSON.parse()
这种方法通过序列化对象为JSON字符串,再反序列化为对象,从而实现深拷贝。但需要注意,这种方法不支持函数、正则表达式、Date对象等非标准JSON数据类型。const source = { name: '小红', age: 25 }; const deepCopy = JSON.parse(JSON.stringify(source));
-
Lodash
Lodash
库的_.cloneDeep()
函数可以轻松实现深拷贝。
const _ = require('lodash');
const source = { name: '小红', age: 25 };
const deepCopy = _.cloneDeep(source);
-
jQuery
jQuery
的$.extend()
函数也可以实现深拷贝,只需传入true
作为第一个参数。const source = { name: '小红', age: 25 }; const deepCopy = jQuery.extend(true, {}, source);
-
如何再来写一个JS实现的方法呢?
obj.hasOwnProperty
无需依赖第三方库,通过简单的递归函数即可实现深拷贝。
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
let copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
浅拷贝与深拷贝的区别
- 基本数据类型:它们都是按值进行复制的。这意味着在拷贝过程中,原始数据和拷贝后的数据是完全独立的,改变其中一个不会影响另一个。
- 引用数据类型:引用数据类型主要包括对象(
Object
)、数组(Array
)、函数(Function
)、日期(Date
)、正则表达式(RegExp
)等。当涉及到这些类型时,浅拷贝与深拷贝之间的行为差异就会显现出来。浅拷贝复制引用,深拷贝复制引用指向的对象。
如何选择?
- 简便性:仅需复制顶层属性时,浅拷贝足矣。
- 性能要求:性能要求高时优先考虑浅拷贝。
- 数据结构:数据结构较复杂时倾向于深拷贝。
- 修改原始对象:避免影响原始数据时,使用深拷贝。
总结来说,当你需要确保拷贝后的对象与原始对象完全独立,互不影响时,应该使用深拷贝。而如果你只是需要一个包含基本类型属性的副本,或者知道拷贝的对象中不会包含需要修改的引用类型,那么浅拷贝就足够了,同时它也更节省资源和执行时间。
看到这里,如果觉得本文对你有用的话还请不吝赐赞👍||😀
转载自:https://juejin.cn/post/7387999151412330531