对象克隆

142 阅读3分钟

一.什么是对象克隆?

在js中对象克隆就是把对象值重新赋给一个新对象。克隆也存在深克隆于浅克隆的区别,引用类型的值都会被保存在堆内存中,在栈内存中会存在一个指针指向堆内存中的值,这时,如果只复制了指针,则可以说这个克隆为浅克隆。如果根据指针找到具体的值,复制值,就可以称之为深克隆。

二.js对象克隆的几种方法

1.JSON

JSON多用于前后台的数据交互,后台传递字符串类型的JSON数据,前端通过JSON.parse() ,可以转化为一个json对象。现有一个对象,可以通过JSON.stringify() 转为json字符串。字符串类型的值保存在栈内存当中,所以可以直接赋值达到深度克隆的结果。最后通过JSON.parse(),就可以实现深度克隆了。

var obj = {
    x: 1,
    y: {
        a: 1,
        b: 0,
        c: [1, 2, 3]
    }
};
// 直接等于号赋值,如果是基本类型的数据,这样足够达到深度克隆
var obj2 = obj;
console.log(obj2 == obj); //true 直接复制只是复制对象的指针,还指向同一个对象
// 转化为了字符串
var obj3 = JSON.parse(JSON.stringify(obj));
console.log(obj3 == obj) //false  通过json方法复制后的地址不一样
console.log(obj3); // 达到深度克隆
  • 缺点:对象名如果是Symbol类型的是无法克隆的。

  • - 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;

  • - 如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;

  • - 如果obj里有function,Symbol 类型,undefined,则序列化的结果会把函数或 undefined丢失;

  • - 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null

  • - JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;

2.Obiect.create()

Object.create()用于把一个对象用于另一个对象的原型,这种以原型的方式来设置一个对象在某个方面也算的上是一种克隆,也可以间接的达到目的。

var obj = {
    x: 1,
    y: {
        a: 1,
        b: 0,
        c: [1, 2, 3]
    }
};

var obj2 = Object.create(obj);
console.log(obj2 == obj); //false
console.log(obj === obj2.__proto__); // true
console.log(obj2); // 输出{}

因为只是把对象设置为新对象的原型,所以新对象不会和原来的对象相等,但是原对象会与新对象的原型相等。一般来说对克隆出来的对象作修改,被克隆的对象没有被修改,就可以判定是一个深克隆出来的对象。但是要是去修改克隆出来的对象的原型中的属性,肯定会影响被克隆的对象,这样来看,又不像深克隆。所以是不是深克隆,界限不是很明确。不通过 _ _ proto_ _ 去访问原型上的对象进行修改也不会改变被克隆对象。

3. ..运算符

运算符可以用于收集对象的所有属性和数组的所有值

let arr = [1,2,3,4,5];
let arr2 = [...arr];
console.log(arr === arr2); // false 
console.log(arr2); // [1, 2, 3, 4, 5]

克隆出来的他俩不相等,那么这就可以判定这样是深克隆了吗。没错,这就可以这样判定,但是对象就不一定了。 如果对象的属性还是对象,那么就会出现意外,对象的属性都是基本类型的值的话,还是深度克隆。

let obj1 = {
    a : 1,
    b : '2',
    c : true,
    d : {
        x : 'd'
    }
}
let obj2 = {...obj1};\
console.log(obj1 === obj2); // false

obj2.d.x = null; // 修改克隆出来的对象的属性d的属性x
console.log(obj1, obj2);

QQ图片20211108155412.png

4.assign

assign为ES7中的方法。方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 这个方法就是一个纯浅克隆

let obj1 = {
    a : 1,
    b : '2',
    c : true,
    d : {
        x : 'd'
    }
}
let obj2 = Object.assign(obj1);
console.log(obj1 === obj2); // true