深拷贝和浅拷贝的区别,如何实现一个深拷贝

发布于:2024-05-08 ⋅ 阅读:(23) ⋅ 点赞:(0)

在JavaScript中,数据类型分为基本数据类型和引用数据类型。

基本数据类型是保存在栈内存中的,引用数据类型的变量是一个指向堆内存中实际对象的引用,这个引用是保存在栈内存中。

浅拷贝

浅拷贝,指的是创建新的数据。

如果原始数据的属性是基本类型,那拷贝的就是基本类型的值;如果原始数据的属性是引用类型,那拷贝的就是内存地址。浅拷贝是拷贝一层,引用类型部分共享内存地址。

实现一个浅拷贝功能的函数

function shallowClone(obj) {
  const newObj = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key]

    }
  }
  return newObj
}

在JavaScript中,提供一个浅拷贝的函数:

  • Object.assign()
  • 使用拓展运算符实现复制
  • Array.prototype.slice()和Array.prototype.concat()

Object.assign

var obj = {
  age: 18,
  nature: ['smart', 'good'],
  names: {
    name1: '11',
    name2: '222'
  },
  love: function () {
    console.log('33333')
  }
}
var newObj = Object.assign({}, obj)

slice()

const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.slice(0)
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]

concat()

const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.concat()
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]

使用拓展运算符实现复制

const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]

深拷贝

深拷贝是开辟一个新的内存空间,两个对象属性完全相同,但是对应的两个不同地址。修改一个对象的属性,不会影响另一个对象。

常见的深拷贝函数:

  1. _.cloneDeep(),lodash库中的一个函数
  2. JSON.stringify()
  3. 手写循环递归

其中的JSON.stringify()会有一些弊端,它会忽略undefined 、Symbol和函数。

循环递归

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; // 如果是null或者undefined,就不进行遍历
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
 
  if (typeof obj !== "object") return obj;
  // 普通值或者函数,不需要遍历
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
 
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

网站公告

今日签到

点亮在社区的每一天
去签到