深拷贝

实现 JavaScript 的深拷贝

// 通过 `Object` 原型对象上的 `toString` 方法,配合正则表达式的分组功能,获取数据的真实类型
// Number BigInt String Boolean Symbol Undefined Null Object Array Promise Function 等等
function getType(data) {
    return Object.prototype.toString.call(data).match(/\[object (\w+)\]/)[1];
}

function deepCopy(data) {
    const dfs = d => {
        const type = getType(d);
        if (type === 'Array') {
            const tmp = [];
            d.forEach(item => {
                tmp.push(dfs(item));
            });
            return tmp;
        }
        if (type === 'Object') {
            // 复制原对象的原型对象
            const tmp = Object.create(Object.getPrototypeOf(d));
            // getOwnPropertyNames 可以获得当前对象的所有属性,即使 enumerable 为 false
            Object.getOwnPropertyNames(d).forEach(key => {
                // 获取当前属性的配置
                const discriptor = Object.getOwnPropertyDescriptor(d, key);
                // 将当前属性配置中的 value 改为深拷贝后的值
                discriptor.value = dfs(discriptor.value);
                // 在 tmp 中定义配置
                Object.defineProperty(tmp, key, discriptor);
            });
            return tmp;
        }
        return d;
    }
    return dfs(data);
}

测试效果:

const data = {
    name: 'weixin',
    age: [27, 25]
};
data.__proto__.try = function() {};
Object.defineProperty(data, 'age', {enumerable: false, writable: false});
const copiedData = deepCopy(data);
console.log('原对象: ', data);
console.log('新对象: ', copiedData);

版权

本作品采用 CC BY-NC-ND 4.0 授权。