返回

深入浅出讲解拷贝

前端




一、拷贝的本质

拷贝,本质上是一种复制行为,将一个变量中的值复制到另一个变量中。拷贝通常是为了保存数据的副本,以便在需要时使用。

二、基本数据类型与对象数据类型的拷贝

基本数据类型的数据,如字符串、数字和布尔值,在拷贝时,会被直接复制到另一个变量中。例如:

let name = "John";
let copyName = name;

在上面的代码中,copyName变量的值等于name变量的值。如果name变量的值发生改变,copyName变量的值也不会改变。这是因为基本数据类型的数据在内存中是按值存储的。

对象数据类型的数据,如数组、对象和函数,在拷贝时,不会被直接复制到另一个变量中。相反,另一个变量会存储对该对象的引用。例如:

let person = {
  name: "John",
  age: 30
};
let copyPerson = person;

在上面的代码中,copyPerson变量的值等于对person对象的引用。如果person对象的值发生改变,copyPerson对象的值也会改变。这是因为对象数据类型的数据在内存中是按引用存储的。

三、浅拷贝与深拷贝

浅拷贝是一种只拷贝对象的第一层属性的拷贝方式。这意味着浅拷贝只会拷贝对象本身的属性,而不会拷贝对象引用的其他对象。例如:

let person = {
  name: "John",
  age: 30,
  address: {
    city: "New York",
    state: "NY"
  }
};
let copyPerson = Object.assign({}, person);

在上面的代码中,copyPerson变量的值是person对象的浅拷贝。copyPerson变量具有nameage属性,但没有address属性。这是因为address属性是一个对象,浅拷贝不会拷贝对象引用的其他对象。

深拷贝是一种拷贝对象的所有属性的拷贝方式。这意味着深拷贝不仅会拷贝对象本身的属性,还会拷贝对象引用的其他对象。例如:

let person = {
  name: "John",
  age: 30,
  address: {
    city: "New York",
    state: "NY"
  }
};
let copyPerson = JSON.parse(JSON.stringify(person));

在上面的代码中,copyPerson变量的值是person对象的深拷贝。copyPerson变量具有nameageaddress属性。这是因为深拷贝会拷贝对象的所有属性,包括对象引用的其他对象。

四、JavaScript中的特殊场景——引用类型拷贝

JavaScript中,引用类型的数据,如数组和对象,在拷贝时,实际上是拷贝了对该对象的引用。这意味着,如果两个变量都指向同一个对象,那么这两个变量的值就是相同的。例如:

let person = {
  name: "John",
  age: 30
};
let copyPerson = person;

person.name = "Bob";

console.log(copyPerson.name); // "Bob"

在上面的代码中,copyPerson变量的值等于对person对象的引用。当person对象的值发生改变时,copyPerson对象的值也会改变。这是因为两个变量都指向同一个对象。

如果要创建一个新的对象,而不是拷贝一个对象的引用,可以使用Object.assign()方法或JSON.parse(JSON.stringify())方法。例如:

let person = {
  name: "John",
  age: 30
};
let copyPerson = Object.assign({}, person);

person.name = "Bob";

console.log(copyPerson.name); // "John"

在上面的代码中,copyPerson变量的值是person对象的浅拷贝。copyPerson变量具有nameage属性,但没有address属性。这是因为address属性是一个对象,浅拷贝不会拷贝对象引用的其他对象。

let person = {
  name: "John",
  age: 30
};
let copyPerson = JSON.parse(JSON.stringify(person));

person.name = "Bob";

console.log(copyPerson.name); // "John"

在上面的代码中,copyPerson变量的值是person对象的深拷贝。copyPerson变量具有nameageaddress属性。这是因为深拷贝会拷贝对象的所有属性,包括对象引用的其他对象。