简述深浅拷贝

引言

浅拷贝:copy对象值的改变会引起原对象值的改变
深拷贝:copy对象值的改变不会引起原对象值的改变

浅拷贝

  1. 方法一 ( = 赋值)
let test = {
  name: 'test',
};
let demo = test;
demo.name = 'demo';
console.log(test); // { name: 'demo' }
console.log(demo == test);
  1. 方法二 (Object.assign) 二级属性
//注意:copy类型必须有二级属性,且浅拷贝的是二级属性对象
let test = {
  name: 'test',
  arr: [1, 2],
};
let demo = Object.assign({}, test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 3, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // true
  1. 方法三(…展开运算符 ) 二级属性
//表现与Object.assign一样
let test = {
  name: 'test',
  arr: [1, 2],
};
let demo = {...test};
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 3, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // true

深拷贝

1.方法一 (JSON.parse.stringify)

//注意:无法拷贝一些特殊属性如:undefined,Date,RegExp,循环引用
let test = {
  name: 'test',
  arr: [1, 2],
};
let demo = JSON.parse(JSON.stringify(test));
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false

2.方法二 (JQuery.extend)

//用法跟Object.assign差不多
//第一个参数为true时为深拷贝,默认false为浅拷贝
let test = {
  name: 'test',
  arr: [1, 2]
};
let demo = $.extend(true, {}, test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
  1. 方法三(lodash.cloneDeep)
//loadash函数库
let test = {
  name: 'test',
  arr: [1, 2]
};
let demo =  _.cloneDeep(test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false
  1. 方法四 (手写)
let test = {
  name: 'test',
  arr: [1, 2]
};
let demo =  deepCopy(test);
demo.name = 'demo';
demo.arr[0] = 3;
console.log(test); //{ name: 'test', arr: [ 1, 2 ] }
console.log(demo);// { name: 'demo', arr: [ 3, 2 ] }
console.log(demo.arr == test.arr); // false

// map 解决循环引用
function deepCopy(source, map = new Map()) {
  if (source instanceof Date) return source;
  if (source instanceof RegExp) return source;
  if (typeof source === 'object') {
    let target = Array.isArray(source) ? [] : {};
    if (map.get(source)) {
      return map.get(source);
    }
    map.set(source, source);
    for (const key in source) {
      target[key] = deepCopy(source[key], map);
    }
    return target;
  } else {
    return source;
  }
}

特殊数据(供深拷贝测试)

let test = {
  a: 1,
  b: {
    b1: 2,
    b2: 3
  },
  c: ['1', '2', '3'],
  d: undefined,
  e: new Date(),
  f: /[a-zA-Z]/g,
}
//循环引用
test.a = test;

其他

深拷贝(一级属性)

// Object.assign()
// ...展开运算符
//Array.slice
//Array.concat
//Array.map
//总之数组方法能够返回新数组的都可以
let test = {
  a: 'test',
  b: 0,
  c: false,
}
// let demo = Object.assign({}, test);
let demo = { ...test };
demo.a = 'demo';
demo.b = 1;
demo.c = true;
console.log(test); //{ a: 'test', b: 0, c: false }
console.log(demo); //{ a: 'demo', b: 1, c: true }

let arr = [0, 1, 2, 3];
let num = arr.slice(0);
//let num = arr.concat();
//let num = arr.map( item => item );
num[0] = 3;
console.log(arr); //[ 0, 1, 2, 3 ]
console.log(num); //[ 3, 1, 2, 3 ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值