📜  什么是 JavaScript 中的浅拷贝和深拷贝?

📅  最后修改于: 2022-05-13 01:56:25.463000             🧑  作者: Mango

什么是 JavaScript 中的浅拷贝和深拷贝?

JavaScript 是一种高级的、动态类型的客户端脚本语言。 JavaScript 将功能添加到静态 HTML 页面。与大多数其他编程语言一样,JavaScript 允许支持深拷贝和浅拷贝的概念。

浅拷贝:当使用赋值运算符将引用变量复制到新的引用变量中时,会创建被引用对象的浅拷贝。简单来说,引用变量主要存储它所引用的对象的地址。当一个新的引用变量被赋予旧引用变量的值时,存储在旧引用变量中的地址被复制到新引用变量中。这意味着新旧引用变量都指向内存中的同一个对象。因此,如果对象的状态通过任何参考变量发生变化,则两者都会反映出来。让我们举个例子来更好地理解它。

代码实现

Javascript
var employee = {
    eid: "E102",
    ename: "Jack",
    eaddress: "New York",
    salary: 50000
}
 
 
console.log("Employee=> ", employee);
var newEmployee = employee;    // Shallow copy
console.log("New Employee=> ", newEmployee);
 
console.log("---------After modification----------");
newEmployee.ename = "Beck";
console.log("Employee=> ", employee);
console.log("New Employee=> ", newEmployee);
// Name of the employee as well as
// newEmployee is changed.


Javascript
var employee = {
    eid: "E102",
    ename: "Jack",
    eaddress: "New York",
    salary: 50000
}
console.log("=========Deep Copy========");
var newEmployee = JSON.parse(JSON.stringify(employee));
console.log("Employee=> ", employee);
console.log("New Employee=> ", newEmployee);
console.log("---------After modification---------");
newEmployee.ename = "Beck";
newEmployee.salary = 70000;
console.log("Employee=> ", employee);
console.log("New Employee=> ", newEmployee);


Javascript
const lodash = require('lodash');
var employee = {
    eid: "E102",
    ename: "Jack",
    eaddress: "New York",
    salary: 50000,
    details: function () {
        return "Employee Name: "
            + this.ename + "-->Salary: "
            + this.salary;
    }
}
 
var deepCopy = lodash.cloneDeep(employee);
console.log("Original Employee Object");
console.log(employee);
console.log("Deep Copied Employee Object");
console.log(deepCopy);
deepCopy.eid = "E103";
deepCopy.ename = "Beck";
deepCopy.details = function () {
    return "Employee ID: " + this.eid
        + "-->Salary: " + this.salary;
}
console.log("----------After Modification----------");
console.log("Original Employee Object");
console.log(employee);
console.log("Deep Copied Employee Object");
console.log(deepCopy);
console.log(employee.details());
console.log(deepCopy.details());


输出:

说明:从上面的例子可以看出,修改newEmployee的名字的时候,也反映到了老员工对象上。这可能会导致数据不一致。这称为浅拷贝。新创建的对象与旧对象具有相同的内存地址。因此,对其中任何一个所做的任何更改都会更改两者的属性。为了克服这个问题,使用了深拷贝。如果其中一个从内存中删除,另一个将不复存在。在某种程度上,这两个对象是相互依赖的。

深拷贝:与浅拷贝不同,深拷贝复制旧对象的所有成员,为新对象分配单独的内存位置,然后将复制的成员分配给新对象。这样,两个对象相互独立,并且在对其中任何一个进行任何修改的情况下,另一个不受影响。此外,如果其中一个对象被删除,另一个对象仍保留在内存中。现在要在 JavaScript 中创建对象的深层副本,我们使用 JSON.parse() 和 JSON.stringify() 方法。让我们举个例子来更好地理解它。

代码实现:

Javascript

var employee = {
    eid: "E102",
    ename: "Jack",
    eaddress: "New York",
    salary: 50000
}
console.log("=========Deep Copy========");
var newEmployee = JSON.parse(JSON.stringify(employee));
console.log("Employee=> ", employee);
console.log("New Employee=> ", newEmployee);
console.log("---------After modification---------");
newEmployee.ename = "Beck";
newEmployee.salary = 70000;
console.log("Employee=> ", employee);
console.log("New Employee=> ", newEmployee);

输出:

说明:这里使用 JavaScript 的 JSON.parse() 和 JSON.stringify() 方法创建新对象。 JSON.stringify() 将 JavaScript 对象作为参数,然后将其转换为 JSON字符串。这个 JSON字符串被传递给 JSON.parse() 方法,然后将其转换为 JavaScript 对象。当对象很小并且具有可序列化的属性时,此方法很有用。但是如果对象非常大并且包含某些不可序列化的属性,则存在数据丢失的风险。特别是如果一个对象包含方法,那么 JSON.stringify() 将失败,因为方法是不可序列化的。有更好的深度克隆方法,其中一种是 Lodash,它也允许克隆方法。

Lodash To Deep Copy: Lodash 是一个 JavaScript 库,提供了多种实用功能,Lodash 库中最常用的函数之一是 cloneDeep() 方法。此方法有助于对对象进行深度克隆,还可以克隆不可序列化的属性,这是 JSON.stringify() 方法中的一个限制。

代码实现

Javascript

const lodash = require('lodash');
var employee = {
    eid: "E102",
    ename: "Jack",
    eaddress: "New York",
    salary: 50000,
    details: function () {
        return "Employee Name: "
            + this.ename + "-->Salary: "
            + this.salary;
    }
}
 
var deepCopy = lodash.cloneDeep(employee);
console.log("Original Employee Object");
console.log(employee);
console.log("Deep Copied Employee Object");
console.log(deepCopy);
deepCopy.eid = "E103";
deepCopy.ename = "Beck";
deepCopy.details = function () {
    return "Employee ID: " + this.eid
        + "-->Salary: " + this.salary;
}
console.log("----------After Modification----------");
console.log("Original Employee Object");
console.log(employee);
console.log("Deep Copied Employee Object");
console.log(deepCopy);
console.log(employee.details());
console.log(deepCopy.details());

输出:

说明:两个对象在修改后具有不同的属性。每个对象的方法也有不同的定义并产生不同的输出。

在 javascript 中进行深度复制的更好方法

https://www.geeksforgeeks.org/how-to-deep-clone-in-javascript/