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

前言

上一篇文章给大家介绍了一些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中的深浅拷贝是面试里常考的题目之一,虽然也比较简单,但是给大家介绍了一些进阶版的回答是不是更能提高面试官对你的好感度呢?

相关推荐
清灵xmf17 分钟前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据24 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617733 分钟前
防抖函数--应用场景及示例
前端·javascript
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript