《深浅拷贝》

63 阅读2分钟

深拷贝与浅拷贝

  • 原始值直接存储在栈中;而引用值真实的数据存储在堆内存中,栈内存中存储的只是指向堆内存的引用地址。
  • 浅拷贝是直接拷贝栈数据,原始值拷贝值,引用值拷贝的是指向堆的地址。修改引用值可能会造成所有指向这个地址的对象都会被改变。
  • 深拷贝对于原始值也是直接拷贝栈数据,但对于引用值则是重新在堆中开辟空间存放引用值,栈中地址指向堆中新开辟的空间,与被拷贝的引用值栈中地址指向不同,所以互不干扰。

深拷贝

  • 方案一:利用递归依次遍历引用值,直到找到原始值。
let obj = {
  name: "peter",
  sex: "male",
  age: 18,
  tel: "18642022222",
  hobbit: ['football', 'music', 'moive'],
  mood: null,
  family: {
    'father': {
      name: 'lilei',
      age: 50
    },
    'mother': {
      name: 'hanmeimei',
      age: 45
    }
  }
}

function deepClone(target, origin){
  target = target || {};
  for (const key in origin) {
    if (origin.hasOwnProperty(key)) {
      // 空 || 原始值
      if(origin[key] === null || typeof origin[key] !== 'object'){
        target[key] = origin[key];
      }
      // 引用值
      else{
        // 判断当前数据是数组还是对象
        target[key] = Object.prototype.toString.call(origin[key]) === '[object Array]' ? [] : {};
        // 递归赋值,直到数据变成了原始值
        deepClone(target[key], origin[key]);
      }
    }
  }
  return target;
}

let newObj = {}
let res = deepClone(newObj, obj);
console.log(res);   // {name: 'peter', sex: 'male', age: 18, tel: '18642022222', hobbit: Array(3), …}

res.family.father.age = 80;
console.log(obj.family.father.age);  // 50  原数据未受影响
  • 方案二:利用JSON自带函数。
var obj = {
    name: 'peter',
    age: 18,
    money: undefined,
    mood: null,
    hobbit: ['ball', 'music', 'moive']
}

var targetObj = JSON.parse(JSON.stringify(obj));
console.log(targetObj);         // {name: 'peter', age: 18, mood: null, hobbit: Array(3)}

obj.hobbit[0] = 'read';
console.log(targetObj.hobbit);  // ["ball", "music", "moive"]
console.log(obj.hobbit);        // ["read", "music", "moive"]

弊端是undefined数据无法拷贝。

浅拷贝

  • 方案一:利用 Object.assign(target, origin)。
var obj = {
  name: 'peter',
  age: 18,
  hobbit: ['ball', 'music', 'moive']
}
var targetObj = {};
Object.assign(targetObj, obj);

obj.hobbit[0] = 'read'; // 相应的 obj1.hobbit也会被修改
console.log(targetObj.hobbit[0]); // 'read'
  • 方案二:for in 循环。
var obj = {
  name: '张三',
  age: 20,
  sex: 'male',
  family: {
    father: '李四',
    mother: '王五'
  }
}

function clone(origin, target) {
  target = target || {};
  for (var k in origin) {
    if (origin.hasOwnProperty(k)) {
      target[k] = origin[k];
    }
  }
  return target;
}

var targetObj = clone(obj);
console.log(targetObj); // {name: "张三", age: 20, sex: "male", family: {father: "李四", mother: "王五"}}