浅拷贝
1、Object.assign
| let a = { |
| age: 1 |
| } |
| let b = Object.assign({}, a) |
| a.age = 2 |
| console.log(b.age) |
2、展开运算符 ...
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
深拷贝
1、JSON.parse(JSON.stringify(object))
| let a = { |
| age: 1, |
| jobs: { |
| first: 'FE' |
| } |
| } |
| let b = JSON.parse(JSON.stringify(a)) |
| a.jobs.first = 'native' |
| console.log(b.jobs.first) |
但是该方法也是有局限性的:
会忽略 undefined
会忽略 symbol
不能序列化函数
不能解决循环引用的对象
| let obj = { |
| a: 1, |
| b: { |
| c: 2, |
| d: 3, |
| }, |
| } |
| obj.c = obj.b |
| obj.e = obj.a |
| obj.b.c = obj.c |
| obj.b.d = obj.b |
| obj.b.e = obj.b.c |
| let newObj = JSON.parse(JSON.stringify(obj)) |
| console.log(newObj) |
| |
如果你有这么一个循环引用对象,你会发现并不能通过该方法实现深拷贝
在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列化
| let a = { |
| age: undefined, |
| sex: Symbol('male'), |
| jobs: function() {}, |
| name: 'yck' |
| } |
| let b = JSON.parse(JSON.stringify(a)) |
| console.log(b) |
你会发现在上述情况中,该方法会忽略掉函数和 undefined 。
但是在通常情况下,复杂数据都是可以序列化的,所以这个函数可以解决大部分问题。
2、如果所需拷贝的对象含有内置类型并且不包含函数,可以使用 ####MessageChannel
| function structuralClone(obj) { |
| return new Promise(resolve => { |
| const { port1, port2 } = new MessageChannel() |
| port2.onmessage = ev => resolve(ev.data) |
| port1.postMessage(obj) |
| }) |
| } |
| |
| var obj = { |
| a: 1, |
| b: { |
| c: 2 |
| } |
| } |
| |
| obj.b.d = obj.b |
| |
| |
| |
| const test = async () => { |
| const clone = await structuralClone(obj) |
| console.log(clone) |
| } |
| test() |
3、推荐使用 lodash 的深拷贝函数。
| function deepClone(obj) { |
| function isObject(o) { |
| return (typeof o === 'object' || typeof o === 'function') && o !== null |
| } |
| |
| if (!isObject(obj)) { |
| throw new Error('非对象') |
| } |
| |
| let isArray = Array.isArray(obj) |
| let newObj = isArray ? [...obj] : { ...obj } |
| Reflect.ownKeys(newObj).forEach(key => { |
| newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] |
| }) |
| |
| return newObj |
| } |
| |
| let obj = { |
| a: [1, 2, 3], |
| b: { |
| c: 2, |
| d: 3 |
| } |
| } |
| let newObj = deepClone(obj) |
| newObj.b.c = 1 |
| console.log(obj.b.c) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)