面试官:什么是深拷贝,如何实现?

大家好,今天给大家带来一道常考的面试题。

深拷贝

所谓深拷贝,简单来说,就是将一个东西原模原样的复制一份下来,并且如果我们改变了我们所复制下来的内容,并不会改变原来的样本。举个例子,老师布置了一份作业,我将题目抄了下来,然后你拿我的题目抄了一份(拷贝了一份),然后你写了一份答案(拷贝的内容有所改变),你的答案并不会出现在我的作业里面(不会改变原来的样本)。

实现

要怎么实现一个深拷贝呢?这还不简单,直接上代码:

javascript 复制代码
function copy(msg) {
    return msg
}
let num = 123
let copyNum = copy(num)
console.log(num); // 123
console.log(copyNum); // 123

直接返回我们需要拷贝的数据不就好了,简简单单,看起来没什么毛病,但实际上对于对象而言,我们拷贝的实际上只是对象的引用,因为我们在调用栈中只能找到对象的引用,其实际内容存在在堆中。

css 复制代码
let obj = {
    a: 1,
    b: {
        hobby: 'coding'
    }
}
let copyObj = copy(obj)
copyObj.a = 2
console.log(obj); // { a: 2, b: { hobby: 'coding' } }
console.log(copyObj); // { a: 2, b: { hobby: 'coding' } }

我们发现当我们拷贝的内容发生变化时,原样本的值也会发生变化,这就不是深拷贝了,上面也说了,我们这样做,拷贝的其实只是对象的引用,通过该引用修改的数据其实是同一份数据。所以,我们应该怎么做呢?

  • 如果不是对象,我们直接返回,完全没毛病
  • 如果是对象,我们就应该遍历这个对象,并将其赋值给一个空对象返回出来
css 复制代码
function copy(msg) {
    if (typeof msg !== 'object' || msg === null) {
        return msg
    } else {
        const copyMsg = Array.isArray(msg) ? [] : {}
        for(let i in msg) {
            copyMsg[i] = msg[i]
        }
        return copyMsg
    }
}
let obj = {
    a: 1,
    b: {
        hobby: 'coding'
    }
}
let copyObj = copy(obj)
copyObj.a = 2
console.log(obj); // { a: 1, b: { hobby: 'coding' } }
console.log(copyObj); // { a: 2, b: { hobby: 'coding' } }

是这样吗,感觉没毛病对吧,我们改变了copyObj的内容,obj确实没有发生变化,好像两份数据互不干扰,确实有点深拷贝的味道了。实际上,我们还是遗漏了一个点,也是最容易犯错的一个点,我们来看,obj中的b是一个对象,上面也说了,我们从调用栈取对象,拿到的实际上是对象的引用,所以,两份数据中拿到的都是同一个引用(数据的地址),如果修改数据的话,修改的就是同一份数据了。

ini 复制代码
let copyObj = copy(obj)
copyObj.a = 2
copyObj.b.hobby = 'shopping'
console.log(obj); // { a: 1, b: { hobby: 'shopping' } }
console.log(copyObj); // { a: 2, b: { hobby: 'shopping' } }

你看两份数据的hobby都改了,那么怎么解决这个问题呢?这是不是和上面的问题是一样的呀,咱继续遍历里面的这个对象不就好了。那么还有一个问题,咱也不知道里面嵌套了多少个对象呀,大问题里面有相同的小问题,那不就是递归吗,是的,问题解决了。

javascript 复制代码
function copy(msg) {
    if (typeof msg !== 'object' || msg === null) {
        return msg
    } else {
        const copyMsg = Array.isArray(msg) ? [] : {}
        for(let i in msg) {
            copyMsg[i] = copy(msg[i])
        }
        return copyMsg
    }
}

let obj = {
    a: 1,
    b: {
        hobby: 'coding'
    }
}
let copyObj = copy(obj)
copyObj.a = 2
copyObj.b.hobby = 'shopping'
console.log(obj); // { a: 1, b: { hobby: 'coding' } }
console.log(copyObj); // { a: 2, b: { hobby: 'shopping' } }

哎呀!!! 问题解决,你说完美是不是。好了今天的分享就到这。

假如您也和我一样,在准备春招。欢迎加我微信shunwuyu,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
前端小巷子9 分钟前
JS实现丝滑文字滚动
前端·javascript·面试
oil欧哟19 分钟前
🧐 我用 Vibe Coding 从 0 到 1 打造 AI 产品,上线一个月效果如何?有什么心得?
前端·产品·vibecoding
霍克itxt点top27 分钟前
NestJS 入门到实战 前端必学服务端新趋势无密分享
前端
xiguolangzi28 分钟前
1panel web服务部署
前端
写不出来就跑路31 分钟前
基于 HTML+CSS+JavaScript 的薪资实时计算器(含本地存储和炫酷动画)
javascript·css·html
摘星编程32 分钟前
Cursor Pair Programming:在前端项目里用 AI 快速迭代 UI 组件
前端·人工智能·ui·typescript·前端开发·cursorai
醉方休1 小时前
React Fiber 风格任务调度库
前端·javascript·react.js
保卫大狮兄1 小时前
连锁零售企业如何能更有效地管理门店考勤?
面试·职场和发展
北辰alk1 小时前
React Intl 全方位解析:为你的 React 应用注入国际化灵魂
前端
李白白i单身版1 小时前
前端VUE项目实现静默打印,无需用户手动确认
前端