背景

最近在做数据处理的过程中,遇到一个问题,如下:
后台传递过来一组数据 Array,每个数组元素里面又包含了子对象,我要对这组数据进行处理,但是不想影响到原数组,同时原数组可能会要进行多个方向的数据格式化,为了渲染不同的界面。

原始数据

let data = [
    {
        id: 1,
        name: 'luoxue',
        age: 25
    },
    {
        id: 2,
        name: 'kk',
        age: 22
    },
    {
        id: 3,
        name: 'qiuxia',
        age: 22
    }
];

处理方案

1、直接用 = 赋值

let myData = data; // 我要的数据
let yourData = data; // 你要的数据
myData[0].name = 'luoxue-xu'; // 我要修改成我的名字
yourData[0].name = 'kk-z'; // 你要修改成你的名字
console.log(data[0].name); // kk-z

不管是对 myData 还是对 yourData 操作,都改变了原来的 data,我心慌啊,原数据怎么能乱动呢,要是它主人追究怎么办?我又弱又饿,跑不过也打不过,左思右想,有了第二种思路。

2、用 slice 来实现数组的拷贝,先试试

let myData = data.slice(0); // 传入0 表示截取全部
let yourData = data.slice(0); // 你家的
myData[0].name = 'luoxue-xu'; // 我要修改成我的名字
console.log(data[0].name); // luoxue-xu

看到结果我又懵了,你这是几个意思啊,我死了两千多个脑细胞才想出来的思路,竟然还是会改变,查询的资料显示 slice 确实可以实现拷贝而不改变原数组的功能啊,难道看漏了。
再认真看了遍资料,有点思绪,slice 虽然返回的是一个新数组,但是元素如果是对象,该引用的还是引用,原来如此。
slice 相当于数组的浅拷贝,如果数组中的元素是基本类型,那就可以通过它来实现拷贝。

江湖走马,风也好,雨也罢 ------《道君》

3、用 JSON 转,先转字符串,再转回对象

let myData = JSON.parse(JSON.stringify(data)); // 我家的
let yourData = JSON.parse(JSON.stringify(data)); // 你家的
yourData[0].name = 'kk-z'; // 你名字带走
console.log(data[0].name); // luoxue

咦,还有点靠谱的样子,竟然可以,这么简单,不会有什么坑吧,先用着试试,不过 jQuery.extend 也可以实现,难道它也是这样做的,不太可能,再思考思考。

4、自己写个深拷贝的函数 clone

const clone = (b) => {
  if(Array.isArray(b)) {
    // 数组拷贝
    let obj = [];
    for(let i = 0; i < b.length; i++) {
      obj[i] = clone(b[i]);
    }
    return obj;
  }else if(b instanceof Object) {
    // 对象拷贝
    let obj = {};
    for(let attr in b) {
      obj[attr] = clone(b[attr]);
    }
    return obj;
  }else {
    return b;
  }
}
let myData = clone(data); // 我家的
let yourData = clone(data); // 还是我家的
yourData[0].name = 'luoxue-kk'; // 还是我家的
console.log(data[0].name); // 返回什么,不告诉你,虽然报错了.

有空可以研究一下 Object.assign 的使用。


luoxuexu
220 声望3 粉丝

喜欢如画江山,看书静思


« 上一篇
let语句