likes
comments
collection
share

js中深拷贝与浅拷贝在JavaScript开发中,对象拷贝是一个基础但至关重要的概念,尤其当我们需要在不修改原始数据的情

作者站长头像
站长
· 阅读数 21

在JavaScript开发中,对象拷贝是一个基础但至关重要的概念,尤其当我们需要在不修改原始数据的情况下,对数据进行操作或传递时。对象拷贝分为浅拷贝和深拷贝两种,它们各有千秋,适用于不同的场景。

浅拷贝:表层的复制

浅拷贝仅复制对象的顶层属性,对于基本类型(如字符串、数字、布尔值)直接复制值,而对于引用类型(如对象、数组),它复制的是引用而非值本身。这意味着,虽然你得到了一个“新”对象,但其中的引用类型属性仍然指向同一个内存地址,因此修改任何一个对象都可能影响到另一个。

浅拷贝的实现方式

  1. Object.assign()

Object.assign() 方法可以用来浅拷贝对象。它接受一个目标对象和一个或多个源对象,然后将源对象的所有可枚举属性的值复制到目标对象。这使得我们可以很容易地创建一个浅拷贝。

const source = { name: '小红', age: 25 };
const shallowCopy = Object.assign({}, source);
  1. 扩展运算符(...

扩展运算符可以用来创建一个对象或数组的浅拷贝。它将一个对象或数组的元素解构并复制到新的实例中。

const source = { name: '小红', age: 25 };
const shallowCopy = { ...source };
  1. Array.prototype.slice()(适用于数组)

数组的 slice()concat() 方法都可以用来创建一个数组的浅拷贝。

const array = [1, 2, 3];
const shallowCopy = array.slice();

深拷贝:彻底的复制

深拷贝则是创建一个全新的对象,它不仅复制顶层属性,还会递归地复制所有层级的属性,包括引用类型,确保新对象与原对象完全独立,互不影响。

深拷贝的实现方式

  1. 递归实现

通过递归遍历对象的属性,我们可以实现一个深拷贝的功能。对于每个属性,如果是引用类型,就再次调用深拷贝函数;如果不是,就直接复制其值。

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;
}
  1. JSON.stringify()JSON.parse() 这种方法通过序列化对象为JSON字符串,再反序列化为对象,从而实现深拷贝。但需要注意,这种方法不支持函数、正则表达式、Date对象等非标准JSON数据类型。

    const source = { name: '小红', age: 25 };
    const deepCopy = JSON.parse(JSON.stringify(source));
    
  2. Lodash

Lodash库的_.cloneDeep()函数可以轻松实现深拷贝。

const _ = require('lodash');
const source = { name: '小红', age: 25 };
const deepCopy = _.cloneDeep(source);
  1. jQuery

    jQuery$.extend()函数也可以实现深拷贝,只需传入true作为第一个参数。

    const source = { name: '小红', age: 25 };
    const deepCopy = jQuery.extend(true, {}, source);
    
  2. 如何再来写一个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
评论
请登录