js对象拷贝方法
2023-09-14 09:07:43 时间
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
相关文章
- js字符串拼接的几种方式是_js字符串常用方法
- js 对象转数组 的方法「建议收藏」
- 总结几个对象转数组的方法是_js将对象转为数组
- JS判断数据类型的方法有哪些_c语言数据类型
- 动态加载js的异步与同步方法
- js call方法_recall
- Uncaught SyntaxError: Cannot use import statement outside a module的解决方法(使用Es6语法引入js对象文件报错)
- JS hasOwnProperty()方法:检测一个属性是否是对象的自有属性
- JS字符串的常用属性和方法
- 使用 JavaScript 调用 Linux 命令的实现方法(js调用linux命令)
- 从前端JS里请求Redis资源,搭建高性能应用(前端js请求redis)
- firefoxTBODY用js显示和隐藏时出现错位的解决方法
- js对象之JS入门之Array对象操作小结
- 有关于JS构造函数的重载和工厂方法
- 复制js对象方法(详解)
- js获取GridView中行数据的两种方法分享
- js中widow.open()方法使用详解
- JS实现日期加减的方法
- 以JSON形式将JS中Array对象数组传至后台的方法
- js数组去重的常用方法总结
- js中把JSON字符串转换成JSON对象最好的方法
- js改变鼠标的形状和样式的方法
- js取整数、取余数的方法
- 不到30行JS代码实现Excel表格的方法
- 多个jsp页面共享一个js对象的超级方法
- node.js中的fs.fchmodSync方法使用说明
- 创建js对象和js类的方法汇总
- JS自定义对象实现Java中Map对象功能的方法
- JS交换变量的方法