javascript深拷贝和浅拷贝

    36

浅拷贝

lodash.clone

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

...运算符

Object.assign

Array.prototype.concat()

Array.prototype.slice()

深拷贝

JSON.parse(JSON.stringify())

缺点:只适用JSON安全的对象

  • 循环引用无法拷贝,BigInt报错
  • 丢失对象的constructor
  • Infinity和-Infinity为null
  • 只能序列化对象的可枚举属性
  • 正则,函数,undefined
  • Symbol、undefined,Function会丢失,
  • 正则、Error,Map、Set变空对象
  • NAN会变null
  • 日期 Date 对象变字符串
const test = {  name: "test"};
const data = {  a: "123", 
              b: 123, 
              c: true, 
              d: [43, 2], 
              e: undefined,
              f: null,
              g: function() {    console.log("g");  },
              h: new Set([3, 2, null]),
              i: Symbol("fsd"),
              j: test,
              k: new Map([    ["name", "张三"],    ["title", "Author"]  ]),
              l: NaN,
              m: new RegExp(".*?"),
              n: new Date()
            };

console.log(JSON.parse(JSON.stringify(data)))

1615270182505BbMqiS

lodash.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);

MessageChannel

  1. 如果需要拷贝的对象没有函数,可以使用MessageChannel实现
function deepClone(val) {
  return new Promise(resolve => {
    const { port1, port2 } = new MessageChannel()
    port2.onmessage = e => resolve(e.data)
    port1.postMessage(val)
  })
}

递归实现

  1. 首先实现一个最简单的深拷贝
function deepClone(target) {
 let cloneTarget = {};
 const keys=Object.keys(target)
 for (const key of keys) {
     cloneTarget[key] = target[key];
 }
 return cloneTarget;
};
  1. 如果是原始类型直接返回,引用类型,递归拷贝
function deepClone(target) {
 if(typeof target==='object'){
     let cloneTarget = Array.isArray(target) ? [] : {};
     const keys = Object.keys(target)
     for (const key of keys) {
         cloneTarget[key] = deepClone(target[key]);
     }
     return cloneTarget;
 }else {
     return target
 }
};
  1. 解决循环引用
function deepClone(target,map = new Map()) {
 if(typeof target==='object'){
     let cloneTarget = Array.isArray(target) ? [] : {};
     if (map.has(target)) {
         return target;
     }
     map.set(target, cloneTarget);
     const keys = Object.keys(target)
     for (const key of keys) {
         cloneTarget[key] = deepClone(target[key],map);
     }
     return cloneTarget;
 }else {
     return target
 }
};
  1. 进一步完善

单独处理各个数据类型 funtion map set 等等

function deepClone(target, map = new WeakMap()) {
 if (typeof target === 'object') {
     if (target === null) {//null
         return null
     }
     if(target instanceof Date){
         return target
     }
     let cloneTarget = Array.isArray(target) ? [] : {};
     if (map.has(target)) {
         return target;
     }
     map.set(target, cloneTarget);
     const keys = Object.keys(target)
     for (const key of keys) {
         cloneTarget[key] = deepClone(target[key], map);
     }
     return cloneTarget;
 } else {
     return target
 }
}

Proxy

//todo

评论区
共有评论 0
暂无评论