首页 > 其他分享 >js对象拷贝方法

js对象拷贝方法

时间:2022-08-21 19:11:21浏览次数:77  
标签:obj 对象 Object js source result key 拷贝

Object.create(),浅拷贝

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;
  • 无法拷贝对象的循环引用,如果对象中有循环引用,会报错:
Uncaught TypeError: Converting circular structure to JSON

递归

// 待拷贝的对象
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

PS:长期有大量岗位可内推,如有需要,欢迎扫码关注

 

标签:obj,对象,Object,js,source,result,key,拷贝
From: https://www.cnblogs.com/beileixinqing/p/16610591.html

相关文章

  • Python入门系列(七)开发常说的“累”与“对象”
    类与对象Python是一种面向对象的编程语言。要创建类,请使用关键字classclassMyClass:x=5创建一个名为p1的对象,并打印x的值p1=MyClass()print(p1.x)所有类......
  • js实现多重继承
    定义一个空的父类构造函数,然后通过prototype为该父类添加属性和方法functionPerson(){}Person.prototype.name="人";//为人类创建一个name属性Person.prototype.s......
  • js基础之call、apply
    call与apply的异同相同点:1、都可以用来修改函数内部的this指向2、都会立即执行函数不同点:1、传参方式不同第一个参数都是传递需要指向的obj,之后的传递参......
  • k8s部署Wordpress(定义不同的资源对象文件)
    1)新建namespace(名称空间)新建wordpress-blognamespace,将应用都部署到wordpress-blog这个命名空间下面。[23:17:36root@k8s-master~]#llnamespace.yamlpod.ymlse......
  • 面向对象
    面向过程面向过程程序特点面向过程思想对应的问题:面向过程这种程序设计理念,对应现实生活中某一个点上具体的问题,特别是对应解决问题过程中具体的操作步骤面向过程程......
  • JSON解析器Jackson
    JSON解析器JacksonJSON解析器:常见的解析器:Jsonlib,Gson,fastjson,jacksonnjava对象转为JSON使用步骤导入jackson的相关jar包创建Jackson核心对象ObjectMapper调用ob......
  • Java学习 (25) 对象篇(05)抽象类&接口
    目录抽象类语法实例注意点具体讲解视频(狂神说Java)接口语法实例具体讲解视频(狂神说Java)抽象类abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是......
  • js小项目
    1.点击图片换壁纸《ulclass="a">《li>《imgsrc="E://图片//0.png">《/li>《li>《imgsrc="E://图片//1.png">《/li>《li>《imgsrc="E://图......
  • JAVA对象与JSON转换的各种方法-fastjson
    1<!--https://mvnrepository.com/artifact/com.alibaba/fastjson-->2<dependency>3<groupId>com.alibaba</groupId>4<artifactId>fastjson</artifactId>......
  • Java学习 (24) 对象篇(04)static关键字
    目录static关键字语法实例代码块语法实例引用库语法实例static关键字static在类中修饰成员变量,在方法中则修饰成员方法static在属性中叫做静态属性,在方法中叫做静态......