Js 中的深拷贝和浅拷贝 [手动实现]

33 阅读2分钟

Js 中的数据类型

先讲一下 Js 中的数据类型, 基本数据类型和引用数据类型,怎么区分的?

  • 基本数据数据类型,直接在栈中存储 stack。
  • 引用数据类型,引用在栈中存储,真实数据在堆中存储。

引用数据类型在栈中存储了指针,该指针指向了堆中该实体的起始地址。

所以什么是浅拷贝和深拷贝?

  • 浅拷贝和深拷贝都复制了值和地址,都是为了解决引用类型赋值后互相影响的问题。
  • 浅拷贝:只进行了一层赋值,深层次的引用类型还是共享内存地址,原对象和拷贝对象还是会互相影响。
  • 深拷贝:进行无限层级拷贝,深拷贝后的原对象不会和拷贝对象相互影响。

引用类型直接赋值的时候,两个对象指向同一个地址,就会造成互相影响。

实现浅拷贝

浅拷贝是一点一点地拷贝一个对象。它将创建一个新对象。此对象具有原始对象属性值的精确副本。如果属性是基本类型,它将复制基本类型的值;如果属性是内存地址(引用类型),则复制内存地址。

function shallowCopy(src_obj) {
    var new_obj = {};
    for (var prop in src) {
        // Object.prototype 的一个方法
        // 判断一个对象是否包含自定义属性而不是原型链上的属性
        if src_obj.hasOwnProperty(prop) {
            new_obj[prop] = src_obj[prop];
        }
    }
    return new_obj;
}

实现深拷贝

浅拷贝其实更深一层的对象会指向同一地址,会相互影响。那么考虑用递归的方法来实现深拷贝,当遇到更深一层的对象时,应该递归调用

function deepCopy (target) {
    // 原始类型,无需递归
    if (typeof target !== 'object') {
        return target;
    }
    // 引用类型,创建数组或对象
    const newTarget = Array.isArray(target) ? [] : Object.create(null);
    for (cont key in target) {
        newTarget[key] = deepCopy(target[key]);
    }
    return newTarget;
}