【面试题】JavaScript 深拷贝和浅拷贝 高级_js面试题深浅拷贝新值和旧值(1)

let obj = {name:'zjl712', age:18}
let obj2 = obj;
console.log(obj == obj2) //true

  • Object.assign()

通过 Object 的 assign 方法可以对对象进行深拷贝,缺点是不能对含有多层嵌套结构的对象进行深拷贝。

深拷贝单层结构的对象,改变拷贝对象的值不会改变原始对象的值。

<script>
    let obj = {
        name: 'zjl712', 
        age: 18, 
        getName:function(){
            return this.name
        }
    }
    let obj2 = Object.assign({}, obj)
    console.log(obj == obj2); // false
    obj2.name = 'zjl'
    console.log(obj, obj2);
</script>

尝试拷贝多层嵌套结构对象,改变拷贝对象内嵌套的对象值(obj2.local.nickname)后,原始对象嵌套的值也会跟着改变。改变拷贝对象非嵌套的值,原始对象的值不会跟着变。所以 Object.assign() 只能实现部分深拷贝。

<script>
    let obj = {
        name: 'zjl712', 
        age: 18, 
        getName:function(){
            return this.name
        },
        local: {
            name: 'shanghai',
            nickname: 'modu',
        }
    }
    let obj2 = Object.assign({}, obj)
    console.log(obj == obj2); // false
    obj2.local.nickname = '魔都'
    obj2.name = 'zjl'
    console.log(obj, obj2);
    console.log(obj.local == obj2.local) // true
</script>

  • JSON.stringify() 和 JSON.parse()

JSON.stringify() 方法接收一个对象作为参数,将对象转为 JSON 字符串。JSON.parse() 接收一个 JSON 字符串,将该字符串转为一个对象。结合这两个方法可以对一个对象进行深拷贝。

结合以上两个方法对对象进行深拷贝

let obj = {name: 'zjl712',age: 18}
let obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj == obj2); // false
obj2.name = 'zjl'
console.log(obj, obj2);

当对象属性值含有 函数(function) 时,且含有嵌套对象时。拷贝的值 属性值为函数的属性会丢失 。优点是能对多层嵌套对象进行深拷贝。

let obj = {
    name: 'zjl712', 
    age: 18, 
    getName:function(){
        return this.name
    },
    local: {
        name: 'shanghai',
        nickname: 'modu',
    }
}
let obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj == obj2); // false
obj2.local.nickname = '魔都'
obj2.name = 'zjl'
console.log(obj, obj2);
console.log(obj.local == obj2.local) // false

  • 对象扩展符(…)

使用 ES6 的扩展操作符,使用三个点(…)将原始对象的值拷贝给另一个对象。然而三点扩展符和 Object.assign() 很相似,扩展符不能对多层嵌套对象进行深拷贝。

let obj = {
    name: 'zjl712', 
    age: 18, 
    getName:function(){
        return this.name
    },
    local: {
        name: 'shanghai',
        nickname: 'modu',
    }
}
let obj2 = {...obj}
console.log(obj == obj2); // false
obj2.local.nickname = '魔都'
obj2.name = 'zjl'
console.log(obj, obj2);

  • 递归的方式实现对象的深拷贝

实现含有嵌套结构、函数对象的深拷贝以上方法都无能为力,我们可以用递归的方法完成对象的深拷贝。缺点是对复杂的对象(Buffer、Date 等实例对象)无法实现深拷贝

function myDeepClone(obj){
    let clone;
    // 排除非引用类型数据
    if(obj == null || typeof obj != 'object') return obj;
    if(Array.isArray(obj)){
        // obj 是数组
        clone = new obj.constructor(obj.length)
        obj.forEach((value, index) => {
            clone[index] = typeof value === 'object'?myDeepClone(value):value
        })
    }else{
        // 浅拷贝一份原始数据
        clone = Object.assign({}, obj)
        // 递归 clone 内的每一个属性值
        Object.keys(clone).forEach(key => {
            clone[key] = typeof obj[key] === 'object'?myDeepClone(obj[key]):obj[key]
        })
    }
    return clone;
}

以上递归代码有相似代码(两个 forEach 内的代码),可简化为以下代码:

function myDeepClone(obj){
    let clone;
    if(obj == null || typeof obj != 'object') return obj;
    clone = Object.assign({}, obj)
    Object.keys(clone).forEach(key => {
#### 总结

*   对于框架原理只能说个大概,真的深入某一部分具体的代码和实现方式就只能写出一个框架,许多细节注意不到。

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**

*   算法方面还是很薄弱,好在面试官都很和蔼可亲,擅长发现人的美哈哈哈...(最好多刷一刷,不然影响你的工资和成功率????)

*   在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。



*   要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!



![](https://img-blog.csdnimg.cn/img_convert/41a409bca685b4ea0e0aa1a5589c3e09.png)



第一次跳槽十分忐忑不安,和没毕业的时候开始找工作是一样的感受,真的要相信自己,有条不紊的进行。**如果有我能帮忙的地方欢迎随时找我,比如简历修改、内推、最起码,可以把烦心事说一说**,人嘛都会有苦恼的~

祝大家都有美好的未来,拿下满意的 offer。
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值