面试官:能不能手写浅拷贝和深拷贝?其实只要搞懂引用类型的存储方式

序言

深入了解JavaScript中的拷贝操作 在前面文章中我们了解了JavaScript中拷贝的两种概念,今天我们将要学习一下这两种拷贝的实现原理是怎样的,如果面试官叫我们手写这两种拷贝你会吗,或者不熟悉忘记了,那么我们再来学习或者温故一遍吧!

手写浅拷贝

编写遍历实现浅拷贝的函数

首先,我们需要一个函数,该函数能够接受一个对象作为参数,然后通过遍历该对象的属性,逐个复制到一个新的对象中。以下是一个简单的实现:

js 复制代码
function shalldowCpoy(obj){

    if(typeof obj !== 'object' || obj === null) return //只拷贝引用类型 去除number和null类型
    let objCopy = obj instanceof Array ? []:{}

    for(let key in obj){
    if(obj.hasOwnProperty(key)){
     objCopy[key] = obj[key] //不能obj.key 因为会将key读成字符串
        }
    }
    return objCopy
}

在这个函数中我们首先判断传入的对象是什么类型,如果是number类型或者null类型则返回,只允许拷贝引用类型,然后我们用正则判断该对象是一个object类型还是array类型,如果是数组则创建一个新数组对象,如果是object类型则创建一个对象类型的objCopy变量,然后遍历源对象身上的所有属性,并且复制到新对象身上中。

示例应用

让我们通过一个示例来演示这个浅拷贝函数的应用:

js 复制代码
let obj = {
    name:'啊伟',
    age:18,
    like:{
        type:'coding'
    }
}
let newObj = shalldowCpoy(obj)
obj.like = 'fishing'

console.log(newObj);  

在这个例子中,obj 包含一个两个简单的属性和一个嵌套的对象。通过调用 shallowdowCopy 函数,我们创建了一个浅拷贝 newObj。这个新对象保留了原始对象的结构,但只复制了属性的引用,所以当我们对原对象中的对象属性内容进行修改时,新对象也受到了影响。

限制和注意事项

了解了浅拷贝的实现原理,我们还需要注意的是,这种浅拷贝的方法有其限制。如果对象中有嵌套的对象数组,仅复制了它们的引用,而不是递归复制。此外,该方法无法处理包含特殊值(如函数、undefined等)的对象。

在实际应用中,根据需求和数据结构的复杂性,选择合适的拷贝方法是很重要的。如果需要更全面的复制,可能需要考虑深拷贝方法或使用第三方库来实现更复杂的拷贝逻辑。

手写深拷贝

编写遍历实现深拷贝的函数

首先,我们需要一个函数,该函数能够接受一个对象作为参数,并遍历该对象的所有属性,逐层进行复制。以下是一个简单的实现:

js 复制代码
function deepCopy(obj) {
    if(typeof obj !== 'object' || obj == null) return
    let objCopy = obj instanceof Array ? []:{}
    for(let key in obj) {
        if(obj.hasOwnProperty(key)){
        if(obj[key] instanceof Object){ 判断// obj[key]是不是引用类型
            objCopy[key] = deepCopy(obj[key]) //递归复制嵌套的对象或数组 对obj[key]进行深拷贝然后返回给objCopy[key]
        }else{
            objCopy[key] = obj[key]
        }
    }
}
    return objCopy
}

这里我们首先检查传入的参数是否为对象,如果不是对象或为null,则直接返回该参数。接着,根据传入的对象是数组还是普通对象来创建一个新的空对象或数组 objCopy

然后,函数通过遍历源对象的属性,判断对象或者数组中遍历到的哪一个属性是否是对象,如果是则递归地调用 deepCopy 函数来复制嵌套的对象或数组,如果不是则直接赋值就行。这确保了每一层的对象都是独立复制的,而不是共享引用。

示例应用

让我们通过一个示例来演示这个深拷贝函数的应用:

js 复制代码
let obj = {
    name:'啊伟',
    age:18,
    like:{
        type:'coding'
    }
}

let newObj = deepCopy(obj)
obj.like.type = 'fishing'

console.log(newObj);

在这个例子中,originalObj 包含一个简单的属性和一个嵌套的对象。通过调用 deepCopy 函数,我们创建了一个深拷贝 deepCopiedObj。这个新对象不仅保留了原始对象的结构,而且递归地复制了所有嵌套的对象,所以当我们对原对象中的对象属性内容进行修改时,新对象并没有受到影响。

注意事项

尽管遍历实现的深拷贝是一种常见而有效的方式,但在处理循环引用、特殊值等情况时需要格外小心。这个简单的实现可能对于一般的场景足够,但对于更复杂的应用,可能需要使用更为完善的深拷贝方法,或者考虑使用第三方库,如Lodash的cloneDeep方法。深拷贝是一个相对复杂的操作,因此在实际应用中需要根据具体情况选择合适的方法。

结语

那么到了这里我们今天的文章就结束啦~

创作不易,如果感觉这个文章对你有帮助的话,点个赞吧♥

更多内容关于JSON的结构和方法你是否还记得?忘记了再来看一遍吧

博主的开源Git仓库: gitee.com/cheng-bingw...

相关推荐
恋猫de小郭8 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅15 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606115 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了15 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅15 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅16 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅16 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment16 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅17 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端