目录

🍎 JavaScript 深拷贝与浅拷贝

回顾 JavaScript 中两大类数据类型:基本数据类型与引用数据类型。

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

# 概念

  • 浅拷贝:指的是创建新的数据,这个数据有着原始数据的属性值的一份精确拷贝。

    如果属性是 基本类型,拷贝的值就是基本类型的值;

    如果属性是 引用类型,拷贝的值是 内存地址

    简单地说,浅拷贝就是一层的拷贝,对于深层次引用类型仅共享内存地址。

    • JavaScript 中,存在浅拷贝的现象有:
      • Object.assign
      • Array.prototype.slice() , Array.prototype.concat()
      • 使用拓展运算符实现的复制

🌰 例子 / Object.assign

let obj = {
  age: 18,
  name: 'simon'
}

let newObj = Object.assign({}, obj)
console.log(newObj)
1
2
3
4
5
6
7

🌰 例子 / Array.prototype.slice()

const arr = ['a', 'b', 'c']
const newArr = arr.slice(0)

newArr[0] = 'd'
console.log(arr) // ["a", "b", "c"]
console.log(newArr) // ["d", "b", "c"]
1
2
3
4
5
6

同理,拓展运算符:

const arr = ['a', 'b', 'c']
const newArr = [...arr]

newArr[0] = 'd'
console.log(arr) // ["a", "b", "c"]
console.log(newArr) // ["d", "b", "c"]

1
2
3
4
5
6
7
  • 深拷贝:开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的内存地址。所以修改其中一个对象的属性,不会改变另一个对象的属性。

    常见的深拷贝方式有:

    • _.cloneDeep()
    • jQuery.extend()
    • JSON.stringify()
    • 手写循环递归

🌰 例子 / _.cloneDeep()

const _ = require('lodash');

const obj1 = {
  a: 1,
  b: { f: { g: 1 } },
  c: [1, 2, 3]
};


const obj2 = _.cloneDeep(obj1)
console.log(obj1.b.f === obj2.b.f) // false
1
2
3
4
5
6
7
8
9
10
11

🌰 例子 / 循环递归实现深拷贝:

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj;
  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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  • 浅拷贝与深拷贝的区别:
    • 浅拷贝复制对象时,只复制指向某个对象的指针,而不复制对象本身,新旧对象是共享同一块内存,修改复制后的对象属性会影响原对象。
    • 深拷贝会另外创造一个与原对象一样的对象(新开栈),新对象与原对象不共享内存,修改新对象不会影响原对象。

d9862c00-69b8-11eb-ab90-d9ae814b240d

# 相关实现例子

🌰 例子 / 简单实现浅拷贝:

点击查看
function shallowClone(obj) {
  const newObj = {}
  for (let prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      newObj[prop] = obj[prop]
    }
  }
  return newObj
}
1
2
3
4
5
6
7
8
9

# 参考

📢 上次更新: 2022/09/02, 10:18:16