Skip to content

浅拷贝和深拷贝

直接赋值:赋值的是引用,被复制的对象仍然指向原对象。

浅拷贝:是对内存地址的复制,让目标对象和源对象都指向同一片内存空间

深拷贝:拷贝对象的具体内容,内存地址自主分配,拷贝结束后两个对象值都相等,但内存地址不一样

浅拷贝实现

  1. Object.assign(),拷贝的是对象的属性的引用,而不是对象本身。

Object,assign(target,...sources)

javascript
let obj1 = {a:{a:'hi',b:21}}
let obj2 = Object.assign({},obj1)
obj2.a.a = 'hello'
console.log(obj2.a.a) //'hello'

注意 Object.assign() 可以处理一层的深度拷贝

javascript
let obj1 = {a:1,b:2,c:3}
let obj2 = Object.assign({},obj1)
obj2.b = 20;
console.log(obj1) //{a:1,b:2,c:3} 未被修改
console.log(obj2) //{a:1,b:20,c:3}
  1. 展开操作符(...)
javascript
let obj1 = {a:1,b:2,c:{d:3}}
let obj2 = {...obj1}
  1. for in
javascript
function shallowClone(initializeObj){
	let obj = {};
  for(let item in initializeObj){
  	obj[item] = initializeObj[item];
  }
  return obj;
}

深拷贝实现

  1. 手动复制
javascript
var obj1 = { a: 1, b: 2, c: 3 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 20;
console.log(obj1);
// { a: 1, b: 2, c: 3 } <-- 沒被改到
console.log(obj2);
// { a: 1, b: 20, c: 3 }
  1. JSON.stringifyJSON.parse

JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。

javascript
let obj = {a:1,b:2,c:3}
let newObj = JSON.parse(JSON.stringify(obj))
  1. 递归拷贝
javascript
function deepClone(obj) {
  let objClone = Array.isArray(obj) ? [] : {};
 // 判断obj为数组还是对象创建[]/{}
  if (obj && typeof obj === 'object') {
    for (key in obj) {
    	if (obj.hasOwnProperty(key)) {
          if (obj[key] && typeof obj[key] === 'object') {
            objClone[key] = deepClone(obj[key])
            //判断obj子元素是否为对象,如果是,递归复制
          } else {
            objClone[key] = obj[key]  //简单复制
          }
      }
    }
  }
  return objClone
}
  1. jquery

提供一个$.extend可以用来做 DeepCopy

javascript
var $ = require('jquery');
var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f);//false
  1. lodash

lodash 提供 _.cloneDeep 用来做 Deep Copy

javascript
var _ = require('lodash');
var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
  1. structuredClone

浏览器自带的全局的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝。(最新的浏览器才可使用,旧的浏览器版本可能不支持该方法)

缺点

  • 原型。如果你对一个类的实例使用 structuredClone(),你会得到一个普通的对象作为返回值,因为结构化克隆抛弃了对象的原型链。
  • 函数。如果你的对象包含函数,它们将被悄悄地丢弃。
  • 不可克隆的对象。有些值是不可结构化克隆的,最明显的是 ErrorDOM 节点。这将导致 structuredClone() 被抛出。