JavaScript之深浅拷贝

浅拷贝

Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

const obj1 = {x: 1, y: 2};
const obj2 = Object.assign({}, obj1);

obj2.x = 2;
console.log(obj1) //{x: 1, y: 2} //原对象未改变
console.log(obj2) //{x: 2, y: 2}

const obj1 = {
    x: 1, 
    y: {
        m: 1
    }
};
const obj2 = Object.assign({}, obj1);

obj2.y.m = 2;
console.log(obj1) //{x: 1, y: {m: 2}} 原对象也被改变
console.log(obj2) //{x: 2, y: {m: 2}}

赋值所有对象

// 木易杨
function cloneShallow(source) {
    var target = {};
    for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
        }
    }
    return target;
}

// 测试用例
var a = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    },
    a1: undefined,
    a2: null,
    a3: 123
}
var b = cloneShallow(a);

a.name = "高级前端进阶";
a.book.price = "55";

console.log(b);
// { 
//   name: 'muyiy', 
//   book: { title: 'You Don\'t Know JS', price: '55' },
//   a1: undefined,
//   a2: null,
//   a3: 123
// }

Array.concat()

针对数组能实现类似效果的还有slice()和Array.from()等

const arr = [1,2,3,4,[5,6]];
const copy = arr.concat();
   
copy[0] = 2; 
console.log(arr) // [1,2,3,4,[5,6]];

// 改变数组中的引用类型值,原数组也会跟着改变
copy[4][1] = 7
console.log(arr) // [1,2,3,4,[5,7]];

深拷贝

JSON.parse()和JSON.stringify()

const obj1 = {
    x: 1, 
    y: {
        m: 1
    }
};
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1) //{x: 1, y: {m: 1}}
console.log(obj2) //{x: 1, y: {m: 1}}

obj2.y.m = 2;
console.log(obj1) //{x: 1, y: {m: 1}} 原对象未改变
console.log(obj2) //{x: 2, y: {m: 2}}

这种方法使用较为简单,可以满足基本日常的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是有以下几个缺点:

  • undefined、任意的函数、正则表达式类型以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时);
  • 它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object;
  • 如果对象中存在循环引用的情况无法正确处理。

你可能感兴趣的:(JavaScript之深浅拷贝)