JavaScript浅拷贝实现方式

在 JavaScript 开发中,我们经常需要处理对象或数组的拷贝操作。在实际开发中,常常会遇到浅拷贝的需求,即将一个对象或数组的内容复制到另一个对象或数组中,复制后的新对象或数组与原对象或数组共享一部分数据。本文将介绍 JavaScript 中浅拷贝的实现方式。

一、什么是浅拷贝?

在 JavaScript 中,对象和数组都是引用类型,当我们将一个对象或数组赋值给一个新的变量时,实际上是将原对象或数组的引用赋值给了新变量。

JavaScript浅拷贝实现方式:探究复制对象的最好方法

例如,以下代码将一个对象赋值给一个新变量:

let obj1 = { name: '张三', age: 18 };

let obj2 = obj1;

在这个例子中,obj2 和 obj1 并不是两个不同的对象,而是指向同一个内存地址的两个引用。

在实际开发中,我们可能需要将一个对象或数组的内容复制到另一个对象或数组中,这时就需要进行浅拷贝。

浅拷贝是指仅复制对象或数组的第一层数据结构,如果对象或数组中还包含对象或数组,复制后的新对象或数组与原对象或数组将共享这些引用类型的数据结构,如下图所示:

如图所示,对象 A 包含两个属性 a 和 b,属性 b 的值为一个对象 B,对象 B 又包含两个属性 c 和 d。当对对象 A 进行浅拷贝后,生成一个新的对象 C,对象 C 与对象 A 共享属性 a 和 b,即浅拷贝只复制了对象 A 的第一层结构,而对象 B 只是被引用了一次,对象 C 与对象 A 共享对象 B,即两个对象的地址相同。

二、浅拷贝实现方式

下面将介绍 JavaScript 中几种常见的浅拷贝实现方式。

  • 手动遍历
  • 手动遍历对象或数组,将每个属性或元素复制到新的对象或数组中。这种方式简单易懂,代码可读性高,但对于嵌套层次较多的对象或数组,代码量将会很大。

    function shallowCopy(obj) {
    if (Array.isArray(obj)) {
    return obj.slice();

    } else if (typeof obj === 'object' &
    &
    obj !== null) {
    let newObj = {};

    for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
    newObj[key] = obj[key];

    }
    }
    return newObj;

    } else {
    return obj;

    }
    }

    在这个例子中,我们首先判断待拷贝的对象是数组还是对象。如果是数组,我们使用 slice() 方法进行浅拷贝;如果是对象,我们通过循环遍历对象的属性,并将每个属性复制到新对象中,最后返回新对象。

  • Object.assign()
  • Object.assign() 方法用于将一个或多个对象的属性复制到目标对象中,如果多个对象具有相同的属性,则后续对象中的属性将覆盖先前对象中的属性。Object.assign() 方法只会复制对象的第一层数据结构,如果对象中包含引用类型的属性,则新对象与原对象将共享这些引用类型的属性。

    let obj1 = { name: '张三', age: 18, hobbies: ['coding', 'reading'] };

    let obj2 = Object.assign({}, obj1);

    在这个例子中,我们使用 Object.assign() 方法将对象 obj1 复制到一个新的空对象中,生成一个新的对象 obj2。

    注意,使用 Object.assign() 方法时,第一个参数必须是目标对象,后面的参数是源对象,如果源对象具有相同的属性,则后续对象中的属性将覆盖先前对象中的属性。如果源对象中有属性是引用类型,那么复制后的新对象将与原对象共享这些属性。

  • 扩展运算符
  • 扩展运算符(spread operator)是 ES6 中新增的语法,可以用于展开数组或对象,将它们的内容复制到另一个数组或对象中。扩展运算符只能用于对象或数组的第一层数据结构,如果对象或数组中包含引用类型的属性,则新对象或数组与原对象或数组将共享这些属性。

    let arr1 = [1, 2, 3];

    let arr2 = [...arr1];


    let obj1 = { name: '张三', age: 18, hobbies: ['coding', 'reading'] };

    let obj2 = { ...obj1 };

    在这个例子中,我们使用扩展运算符将数组 arr1 和对象 obj1 的内容复制到新的数组和对象中,生成新的数组 arr2 和对象 obj2。

    扩展运算符使用起来方便简洁,代码可读性高,但对于嵌套层次较多的对象或数组,代码量还是比较大。

  • Array.from()
  • Array.from() 方法用于将一个类数组对象或可迭代对象转换成一个新的数组,可以用于数组的浅拷贝。

    let arr1 = [1, 2, 3];

    let arr2 = Array.from(arr1);

    在这个例子中,我们使用 Array.from() 方法将数组 arr1 转换成一个新的数组 arr2,实现了浅拷贝。

    需要注意的是,Array.from() 方法只能用于类数组对象或可迭代对象的浅拷贝,如果需要对对象进行浅拷贝,还需要使用其他方法。

    三、总结

    本文介绍了 JavaScript 中浅拷贝的实现方式,包括手动遍历、Object.assign() 方法、扩展运算符和 Array.from() 方法。实际开发中,我们可以根据实际需要选择最适合的一种方式进行浅拷贝操作。需要注意的是,浅拷贝只是复制了对象或数组的第一层数据结构,如果对象或数组中包含引用类型的属性,则浅拷贝复制后的新对象或数组与原对象或数组将共享这些属性。如果需要实现深拷贝,则需要使用其他方法进行操作。



    不管是在编写方法库还是小型项目中,都需要复制对象。在 JavaScript 中,复制对象通常用到的是浅拷贝。接下来我们将探究什么是浅拷贝、浅拷贝实现方式,以及它的用途和限制。
    一、什么是浅拷贝
    浅拷贝是指复制一个对象而不拷贝它所有的嵌套对象。即,它只是复制对象的引用,并没有对嵌套对象进行复制。因此,原始对象和新的对象共享嵌套对象。如果修改其中一个对象的嵌套对象,另一个对象也会受到影响。
    二、浅拷贝实现方式
    1. Object.assign()方法
    Object.assign() 方法将所有可枚举属性的值从一个或多个源对象复制到目标对象。它返回目标对象。语法如下:
    ```
    Object.assign(target, ...sources)
    ```
    例子:
    ```
    let obj = {
    a: 1,
    b: 2
    };
    let obj2 = Object.assign({}, obj);
    console.log(obj2); // output: { a: 1, b: 2 }
    ```
    2. 手动复制对象
    可以使用循环和条件语句来手动复制对象。需要注意的是,手动复制仅适用于对象的浅拷贝。
    例子:
    ```
    let obj = {
    a: 1,
    b: 2
    };
    let obj2 = {};
    for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
    obj2[key] = obj[key];
    }
    }
    console.log(obj2); // output: { a: 1, b: 2 }
    ```
    3. 展开运算符
    展开运算符 (...) 可以用于创建新的对象并将原始对象的所有属性复制到新对象。需要注意的是,展开运算符同样适用于对象的浅拷贝。
    例子:
    ```
    let obj = {
    a: 1,
    b: 2
    };
    let obj2 = {...obj};
    console.log(obj2); // output: { a: 1, b: 2 }
    ```
    三、用途和限制
    浅拷贝具有很多使用场景,例如:
    - 对象的复制;
    - 对象的合并;
    - 对象属性分离等等。
    但是,由于它与原始对象共享嵌套对象,因此在修改其中一个对象的嵌套对象时,会影响另一个对象。
    深拷贝可以规避这个问题,但是深拷贝的性能会比浅拷贝低,并且在处理大型对象或繁琐对象时可能会出现问题。因此,开发者需要在实际使用时根据具体情况选择不同的拷贝方式。
    总结:
    在 JavaScript 中,对象浅拷贝是一种常见的操作,因为它可以有效地进行对象复制。对象复制是一种非常灵活的操作,但是每个开发人员都必须明确对象复制会影响到原始对象和新对象之间的共享,需要根据具体情况进行选择最合适的拷贝方式。