前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js对象拷贝方法

js对象拷贝方法

作者头像
蓓蕾心晴
发布2022-08-23 15:37:51
2.4K0
发布2022-08-23 15:37:51
举报
文章被收录于专栏:前端小叙前端小叙
Object.create(),浅拷贝
代码语言:javascript
复制
const clone = Object.create(
  Object.getPrototypeOf(obj),   
  Object.getOwnPropertyDescriptors(obj)
);
Object.assign(targetObj,sourceObj),浅拷贝

不是深拷贝,循环引用、各种数据类型都可以拷贝,引用类型不是深拷贝

  • 它不会拷贝对象的继承属性;
  • 它不会拷贝对象的不可枚举的属性;
  • 不可以拷贝对象中的对象;
  • 可以拷贝 Symbol 类型的属性;
  • 无法正确拷贝属性和属性
  • 可以拷贝undefined/boolean/null/function/Date/RegExp/array/array中的对象;

参考阮一峰文档: https://es6.ruanyifeng.com/#docs/object-methods#Object-assign

扩展运算符,浅拷贝

不是深拷贝,循环引用、各种数据类型都可以拷贝,引用类型不是深拷贝

JSON.parse(JSON.stringfiy()),不完全深拷贝
  • 拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
  • 拷贝 Date 引用类型会变成字符串;
  • 无法拷贝不可枚举的属性;
  • 无法拷贝对象的原型链;
  • 拷贝 RegExp 引用类型会变成空对象;
  • 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
  • 无法拷贝对象的循环引用,如果对象中有循环引用,会报错:
代码语言:javascript
复制
Uncaught TypeError: Converting circular structure to JSON
递归
代码语言:javascript
复制
// 待拷贝的对象
let originObj = {
    re: /hello/,
    ff: function () {},
    sym: Symbol(123),
    date: new Date(),
    mp: new Map(),
    st: new Set(),
    a: "aaa",
    b: 123,
    c: true,
    d: undefined,
    e: null,
    f: {
        f1: "fff",
        f2: { a: "aaa", b: 123, c: true, d: undefined, e: null },
        f3: [{ a: "aaa", b: 123, c: true, d: undefined, e: null }, "f666", 666],
    },
    g: [1, 2, 3],
    h: [{ a: "aaa", b: 123, c: true, d: undefined, e: null }, "f666", 666],
};
var obj222 = {
    a: originObj,
};
originObj.obj222 = obj222;
// 简单实现,缺点:没有考虑 Date/RegExp/Set/Map/循环引用,如果有循环引用会报错栈溢出
function cloneDeep(obj) {
    let objClone = obj.constructor === Array ? [] : Object.create({});
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            // Object.prototype.toString.call(/123/)
            if (obj[key] && typeof obj[key] === "object") {
                objClone[key] = cloneDeep(obj[key]);
            } else {
                objClone[key] = obj[key];
            }
        }
    }
    return objClone;
}
// 详细实现
/**
 * 深拷贝关注点:
 * 1. JavaScript内置对象的复制: Set、Map、Date、RegExp等
 * 2. 循环引用问题
 * @param {*} object
 * @returns
 */
function deepClone(source, memory) {
    const isPrimitive = (value) => {
        return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
            Object.prototype.toString.call(value)
        );
    };
    let result = null;
    let type = Object.prototype.toString.call(source);
    memory || (memory = new WeakMap());
    // 原始数据类型及函数
    if (isPrimitive(source)) {
        // console.log("current copy is primitive", source);
        result = source;
    }
    // 数组
    else if (Array.isArray(source)) {
        result = source.map((value) => deepClone(value, memory));
    }
    // 内置对象Date、Regex
    else if (type === "[object Date]") {
        result = new Date(source);
    } else if (type === "[object RegExp]") {
        result = new RegExp(source);
    }
    // 内置对象Set、Map
    else if (type === "[object Set]") {
        result = new Set();
        for (const value of source) {
            result.add(deepClone(value, memory));
        }
    } else if (type === "[object Map]") {
        result = new Map();
        for (const [key, value] of source.entries()) {
            result.set(key, deepClone(value, memory));
        }
    }
    // 引用类型
    else {
        if (memory.has(source)) {
            result = memory.get(source);
        } else {
            result = Object.create(null);
            memory.set(source, result);
            Object.keys(source).forEach((key) => {
                const value = source[key];
                result[key] = deepClone(value, memory);
            });
        }
    }
    return result;
}

console.log(cloneDeep(originObj));
console.log(deepClone(originObj));

参考:https://github.com/shfshanyue/Daily-Question/issues/203#issuecomment-888238489

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Object.create(),浅拷贝
  • Object.assign(targetObj,sourceObj),浅拷贝
  • 扩展运算符,浅拷贝
  • JSON.parse(JSON.stringfiy()),不完全深拷贝
  • 递归
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档