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

序言

深入了解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...

相关推荐
lichong95125 分钟前
【Flutter&Dart】 listView.builder例子二(14 /100)
android·javascript·flutter·api·postman·postapi·foxapi
落日弥漫的橘_1 小时前
npm run 运行项目报错:Cannot resolve the ‘pnmp‘ package manager
前端·vue.js·npm·node.js
梦里小白龙1 小时前
npm发布流程说明
前端·npm·node.js
No Silver Bullet1 小时前
Vue进阶(贰幺贰)npm run build多环境编译
前端·vue.js·npm
阿华写代码1 小时前
重新面试之JVM
jvm·面试·职场和发展
破浪前行·吴1 小时前
【初体验】【学习】Web Component
前端·javascript·css·学习·html
泷羽Sec-pp2 小时前
基于Centos 7系统的安全加固方案
java·服务器·前端
IT 古月方源2 小时前
GRE技术的详细解释
运维·前端·网络·tcp/ip·华为·智能路由器
myepicure8882 小时前
Windows下调试Dify相关组件(1)--前端Web
前端·llm
用户59594399272192 小时前
大牛工程师告诉你:开关电源“Y电容”都是这样计算的!
前端