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

前言

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

相关推荐
橙露5 小时前
Vue3 组件通信全解析:技术细节、适用场景与性能优化
前端·javascript·vue.js
扉间7985 小时前
lightrag嵌入思路
前端·chrome
无限大65 小时前
为什么"缓存"能提高系统性能?——从 CPU 缓存到分布式缓存
后端·面试
toooooop85 小时前
Vuex Store实例中`state`、`mutations`、`actions`、`getters`、`modules`这几个核心配置项的区别
前端·javascript·vue.js
LYFlied6 小时前
Rust代码打包为WebAssembly二进制文件详解
开发语言·前端·性能优化·rust·wasm·跨端
OpenTiny社区6 小时前
历时1年,TinyEditor v4.0 正式发布!
前端·javascript·vue.js
time_rg6 小时前
深入理解react——1. jsx与虚拟dom
前端·react.js
Keke6 小时前
🍔 fabric如何实现辅助选区捏
前端·javascript
hang_bro6 小时前
echarts 饼图显示设置
前端·echarts
2501_941886866 小时前
基于法兰克福金融系统实践的高可靠消息队列设计与多语言实现经验总结分享
服务器·前端·数据库