当你用熟JavaScript对象深度拷贝之后

时间:2022-01-19 21:32:12

JavaScript对象深度拷贝算是一个老题,时不时开发中也会遇到,有时顺手再写一个,有时直接百度copy省时省力,,不过遇到问题多了之后,时不时就扩展一下,然后发现了一些有趣好玩的东西,不过他们大多不是最优解决方案,只不过提供了一个应用思路(某数学家:遇到新问题,首先看能不能转化成老问题)。

1.对象比较

大家都清楚,在JavaScript中{***}和{***}用==或===比较结果都是false,因为每个对象分配的地址都是不同的,但有时候我们需要比较两个对象的值是否相等,即希望判断{a:1,b:{c:1}}与{b:{c:1},a:1}相等,由于对象是key:value结构,原则上内部是无序结构,所以想要进行深比较,可以使用广度优先递归一层一层的比,因为key不同则必不等,广度优先理想情况下时间复杂度会更优(具体情况可参考其他博文),而这时候,如何你手边正好有个深度拷贝算法,那么加工一下就能改成对象暴力深排序算法,之后再调用JSON.stringify(obj)转化为字符串,相等则等,不等则不等(我给你讲,正则表达式这东西,我是没考虑的哈)。
show you code:

// 深拷贝+排序
function depthSortObject(obj){
    if(obj.constructor !== Object){
      return;
    }
    const newobj = {};
    for(const i in obj){
        newobj[i] = obj[i].constructor === Object ? 
        sortObject(depthSortObject(obj[i])) : obj[i]; 
    } 
    return newobj;
}
// 局部排序对象
function sortObject(obj){
  const newObj = {};
  const objKeys = Object.keys(obj)
  objKeys.sort().map((val) => {
      newObj[val] = obj[val];
  });
  return newObj;
}
console.log(depthSortObject(JSON.stringify({a:1,b:{c:1}}))===depthSortObject(JSON.stringify({b:{c:1},a:1})))

是不是特别暴力···(记得实际开发环境自个儿写或者找更优方案)

2.Mock数据

成熟的Mock的工具推荐大家使用Mock.js,更适合项目开发的还有easyMock、Rap等。这里只是说一下如何魔改深拷贝创造Mock数据(下面是简易版代码,复杂版可以做很多配置,可以前往GitHub查看或下载使用,得亏是自己写同事看到后告诉我有Mock.js,不然看过Mock.js之后我都怀疑自己是抄袭。。。)。

//需要的key与其对应类型
const model = {
  cost: 'int',
  status: 'string',
  lossList: [{
    date: 'string',
    value: [['int','int']],
  }]
};
// 又是深拷贝了
function mockData(obj){
    const newobj = obj.constructor === Array ? [] : {};
    if(typeof obj !== 'object'){
        return;
    } else {
        for(const i in obj){
            newobj[i] = typeof obj[i] === 'object' ? 
            mockData(obj[i]) : mock(obj[i]); 
        }
    }
    return newobj;
}

function mock(type) {
    let data = undefined;
    switch(type){
        case 'int' : 
            data = Math.floor(Math.random() * 99999);
            break;
        case 'float' :
        case 'number' :
            data = (Math.random() * 99999).toFixed(6);
            break;
        case 'string' :
            data = Math.random().toString(36).substr(2);
            break;
        default :
            data = null;
    }
    return data;
}

console.log(mockData(model))

简单粗暴的深拷贝融合替换值,你要说这么实现性能好不好,以我的观点来看不是很理想,不过结合应用场景,mock数据传过来的json或object的key不会很复杂,所以实际体验效果是很棒的。

······肯定还有很多黑用法没发现,等我到时候遇到了再补