深拷贝函数

本文详细介绍了JavaScript中深拷贝的概念,包括浅拷贝和深拷贝的区别,并提供了深拷贝的基础实现。通过JSON序列化的方法存在局限性,如处理不了函数、Symbol等特殊类型,以及循环引用的问题。因此,文章提供了一个自定义深拷贝函数的实现,涵盖了处理Symbol、函数、数组、对象、Set和Map等复杂数据类型,以及解决循环引用的策略。测试代码验证了该深拷贝函数的正确性。
摘要由CSDN通过智能技术生成

深拷贝函数

1、深拷贝基础

  • 对象赋值的三种方式
    • 引用赋值:指向同一个对象,相互之间会影响;
    • 浅拷贝:浅层的拷贝,内部引入对象时,依然会相互影响;
    • 深拷贝:两个对象不再有任何关系,不会相互影响;
  • 实现深拷贝的方式:
    • 通过JSON序列化
    • 但是会存在bug
    • 对函数、Symbol等无法处理
    • 如果存在对象循环引用,会报错
  • 自定义深拷贝函数
    • 实现深拷贝基本功能
    • 对Symbol的key做处理
    • 对其他数据类型的值进行处理:数组、函数、Symbol、Set、Map
    • 对循环引用做处理

2、基本实现

// 浅拷贝的实现
// 只能拷贝第一层,如果碰到Object类型仍然的引用
function deepClone(originValue) {
  const newObject = {};
  for (const key in originValue) {
    newObject[key] = originValue[key];
  }
  return newObject;
}

// 测试代码
const obj = {
  name: 'byj',
  age: 18,
  friend: {
    name: 'abc',
  },
};

const newObj = deepClone(obj);
console.log(newObj === obj);
// 深拷贝的基本实现
// 优化1:数组or对象
// 优化2:函数,函数进行复用,函数进行赋值而不是额外拷贝一个新的函数,如果是函数则直接返回
// 优化3:symbol类型
// set和map只是做了浅层拷贝
// 优化4:set处理
// 优化5:map处理
function isObject(value) {
  const valueType = typeof value
  return (value !== null) && (valueType === "object" || valueType === "function")
}

function deepClone(originValue) {
  // instanceof判断某个对象是否为真实的构造函数类型
  // 优化4,判断是否是一个Set类型
  if (originValue instanceof Set) {
    return new Set([...originValue]);
  }

  // 优化5,判断是否是一个Map类型
  if (originValue instanceof Map) {
    return new Map([...originValue]);
  }
  
  // 优化3,判断如果是Symbol的value, 那么创建一个新的Symbol
  if (typeof originValue === "symbol") {
    return Symbol(originValue.description)
  }
  
  // 优化2,判断如果是函数类型, 那么直接使用同一个函数
  if (typeof originValue === "function") {
    return originValue
  }
  
  // 判断传入的originValue是否是一个对象类型
  // 如果不是对象类型,则直接返回,做一个赋值操作,将旧的值赋值给新的对象
  if (!isObject(originValue)) {
    return originValue
  }

  // 优化1,判断传入的对象是数组, 还是对象
  const newObject = Array.isArray(originValue) ? []: {}
  for (const key in originValue) {
    newObject[key] = deepClone(originValue[key])
  }
  // symbol无法当作key被遍历,所以需要另外处理
  // 对Symbol的key进行特殊的处理
  const symbolKeys = Object.getOwnPropertySymbols(originValue);
  for (const sKey of symbolKeys) {
    newObject[sKey] = deepClone(originValue[sKey]);
  }
  return newObject
}


// 测试代码
let s1 = Symbol("aaa")
let s2 = Symbol("bbb")

const obj = {
  name: 'byj',
  age: 18,
  friend: {
    name: 'abc',
  },
  hobbies: ["abc", "cba", "nba"],
  // 函数类型
  foo: function( ) {
    console.log("foo function")
  },
  // Symbol作为key和value
  [s1]: "abc",
  s2: s2,
  // Set/Map
  set: new Set(['aaa', 'bbb', 'ccc']),
  map: new Map([
    ['aaa', 'abc'],
    ['bbb', 'cba'],
  ]),
};

const newObj = deepClone(obj)
console.log(newObj === obj)
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值