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

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

深拷贝

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

实现

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

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,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
小码哥_常2 小时前
一套自己部署的 IM,客户端是同一份 Flutter
前端·后端
蜗牛攻城狮4 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
她说可以呀6 小时前
Vue插槽
前端·javascript·vue.js
qq_448011166 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan6 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
Yuzhiyuxia7 小时前
【AI Agent面试系列】AI Agent记忆机制知识点1
人工智能·面试·职场和发展
2601_958352907 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝7 小时前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing038 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel8 小时前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端