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

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

深拷贝

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

实现

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

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 分钟前
React 19 + Vite 6 + SWC 构建优化实践
前端·react.js·vite·swc
Highcharts.js11 分钟前
使用Highcharts与React集成 官网文档使用说明
前端·react.js·前端框架·react·highcharts·官方文档
这是个栗子12 分钟前
AI辅助编程(二) - 通译千问
前端·ai·通译千问
VT.馒头23 分钟前
【力扣】2625. 扁平化嵌套数组
前端·javascript·算法·leetcode·职场和发展·typescript
cyforkk27 分钟前
09、Java 基础硬核复习:异常处理(容错机制)的核心逻辑与面试考点
java·数据库·面试
数研小生1 小时前
Full Analysis of Taobao Item Detail API taobao.item.get
java·服务器·前端
Shirley~~1 小时前
Vue-skills的中文文档
前端·人工智能
毎天要喝八杯水1 小时前
搭建vue前端后端环境
前端·javascript·vue.js
计算机程序设计小李同学2 小时前
幼儿园信息管理系统的设计与实现
前端·bootstrap·html·毕业设计
雨季6662 小时前
Flutter 三端应用实战:OpenHarmony “极简手势轨迹球”——指尖与屏幕的诗意对话
开发语言·javascript·flutter