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

序言

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

相关推荐
mCell11 分钟前
[NOTE] JavaScript 中的稀疏数组、空槽和访问
javascript·面试·v8
柒儿吖16 分钟前
Electron for 鸿蒙PC - Native模块Mock与降级策略
javascript·electron·harmonyos
豆奶特浓628 分钟前
Java面试生死局:谢飞机遭遇在线教育场景,从JVM、Spring Security到AI Agent,他能飞吗?
java·jvm·微服务·ai·面试·spring security·分布式事务
颜酱32 分钟前
package.json 配置指南
前端·javascript·node.js
todoitbo38 分钟前
基于 DevUI MateChat 搭建前端编程学习智能助手:从痛点到解决方案
前端·学习·ai·状态模式·devui·matechat
oden43 分钟前
SEO听不懂?看完这篇你明天就能优化网站了
前端
IT_陈寒1 小时前
React性能优化:这5个Hooks技巧让我减少了40%的重新渲染
前端·人工智能·后端
Sunhen_Qiletian1 小时前
《Python开发之语言基础》第六集:操作文件
前端·数据库·python
珑墨1 小时前
【唯一随机数】如何用JavaScript的Set生成唯一的随机数?
开发语言·前端·javascript·ecmascript
L***d6701 小时前
十七:Spring Boot依赖 (2)-- spring-boot-starter-web 依赖详解
前端·spring boot·后端