当面试官让你谈谈深浅拷贝,你怎么说?

前言

上一篇文章给大家介绍了一些js方面的考题,相信应该对大家应该有所帮助。深浅拷贝也是js中常考的一道题,常见的回答相信大家都见过了,那么这篇文章就带你看看进阶版的回答。
前端面试必考八股文之------js系列(1)

是什么?

  • 浅拷贝
    只拷贝一层对象,复制这一层对象中原始类型的属性值,如果有引用类型的话,就复制它的指针(引用地址)
  • 深拷贝
    层层拷贝,所有类型的属性值都会被复制,原对象的修改不会影响拷贝后的对象
  • 深浅拷贝通常只针对引用类型:
    原始类型拷贝后修改原属性值不会对拷贝后的值产生影响,所以讨论原始类型的深浅拷贝没有意义,或者说原始类型都是深拷贝

如何实现深浅拷贝的效果?

  • 浅拷贝
    Object.assign concat slice [...arr]
    这里很多人会有疑惑,concatslice不是数组上面的方法吗?但是大家可能忽略了一个问题,数组也是引用类型,深浅拷贝针对的是所有的引用类型,所以数组也算在内。
js 复制代码
let obj = {
    a: 1,
    b: 2
}
let newObj = Object.assign({}, obj)

let arr = [1,2,3]
let newArr = [].concat(arr)
arr.push(4)
console.log(newArr);    // [1,2,3],不影响新数组

// 但是如果这样写就会影响
let arr2 = [1,2,3,{n: 4}]
let newArr2 = [].concat(arr2)
arr2[3].n = 5
console.log(newArr2);   // [1,2,3,{n: 5}]

let newArr = arr.slice(0,arr.length)
let newArr = [...arr]

其实还有一个方法,也能实现浅拷贝效果,就是Object.create(obj),但是它一般不放在浅拷贝的范畴里。

js 复制代码
let obj = {
    a: 1,
    b: 2
}
let newObj2 = Object.create(obj)
console.log(newObj2);   // {}
console.log(newObj2.a);   // 1

因为Object.create(obj)创建了一个新的空对象newObj2,让newObj2隐式继承了obj的属性,即执行了一个这样的操作newObj2.__proto__ = obj,深浅拷贝一般指的是拷贝对象上的显式具有的属性,所以Object.create(obj)就没被算在内,但是你把这个告诉面试官,同样会让他对你眼前一亮。

  • 深拷贝
    实现深拷贝就这一个方法JSON.parse(JSON.stringify(obj)),但是它有一个缺陷就是不能拷贝undefinedSymbolfunction,它的原理很简单,就是把对象先转为字符串,然后再转为对象,这样拷贝前后的两个对象就是两个单独的个体,有两个不同的引用地址,就不会相互影响。

如何实现深浅拷贝?

注意审题哦,这里说的是如何实现深浅拷贝?,而不是如何实现深浅拷贝的效果?,它的意思是让你手动实现深浅拷贝,要你手撕代码。

  • 浅拷贝
    这里就有一点要注意一下,拷贝是拷贝对象显式具有的属性,所以在拷贝前要先判断该属性是不是对象显式具有的
js 复制代码
function shallowCopy(obj) {
    let newObj = {}
    for (let key in obj) {
        // 判断该属性是否是原对象显式具有的属性
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key]
        }        
    }
    return newObj
}
  • 深拷贝:
    实现深拷贝常见的就是递归,相信很多人都会选择用这个方法。
js 复制代码
function deepCopy(obj) {
    let newObj = {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] !== 'object' || obj[key] === null) {    // 原始类型
                newObj[key] = obj[key]
            } else {
                newObj[key] = deepCopy(obj[key])
            }
        }
    }

    return newObj
}

这里再给大家介绍一个进阶版的方法structuredClone(obj),这是es6新增的专门用来实现深拷贝的方法,但它一样有个缺陷,就是不能拷贝Symbolfunction

但是相较于JSON.parse(JSON.stringify(obj))来说,它能够拷贝undefined

js 复制代码
let obj = {
    a: 1,
    b: {
        n: 2
    },
    c: undefined
}
const obj2 = structuredClone(obj)
console.log(obj2);   // { a: 1, b: { n: 2 }, c: undefined }

结语

js中的深浅拷贝是面试里常考的题目之一,虽然也比较简单,但是给大家介绍了一些进阶版的回答是不是更能提高面试官对你的好感度呢?

相关推荐
walking9572 分钟前
重新学习前端之TypeScript
前端·javascript·面试
walking9572 分钟前
重新学习前端之Linux
前端·vue.js·面试
walking9573 分钟前
重新学习前端之CSS
前端·vue.js·面试
walking9573 分钟前
重新学习前端之Git
前端·vue.js·面试
walking9573 分钟前
重新学习前端之小程序
前端
魔术师Grace5 分钟前
AI让我退化成原始人了
前端·程序员
铁皮饭盒6 分钟前
今天你会学到这些关键词
前端·后端
李剑一7 分钟前
耗时 2 小时!我复刻了全网超火的通透 3D 水晶球动效,Vue3+Three.js 做出高级视觉特效
前端·three.js
oil欧哟14 分钟前
🤔 很长时间没写文章了,分享一下最近的一些思考
前端·后端
Hello--_--World1 小时前
Vue指令:v-if vs v-show、v-if 与 v-for 的优先级冲突、自定义指令
前端·javascript·vue.js