深浅拷⻉ 【面试】

深浅拷⻉ 面试

⾸先可以通过 Object.assign 来解决这个问题,很多⼈认为这个函数是⽤来 深拷⻉的。其实并不是,Object.assign只会拷⻉所有的属性值到新的对象 中,如果属性值是对象的话,拷⻉的是地址,所以并不是深拷⻉。

let a = {
 age: 1 }
let b = Object.assign({}, a) a.age = 2
console.log(b.age) // 1

另外我们还可以通过展开运算符...来实现浅拷⻉

let a = {
 age: 1 }
let b = { ...a } a.age = 2
console.log(b.age) // 1

通常浅拷⻉就能解决⼤部分问题了,但是当我们遇到如下情况就可能需要使⽤ 到深拷⻉了

let a = {
 age: 1,
 jobs: {
 first: 'FE'
 } }
let b = { ...a } a.jobs.first = 'native'
console.log(b.jobs.first) // native

浅拷⻉只解决了第⼀层的问题,如果接下去的值中还有对象的话,那么就⼜回 到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使⽤深拷⻉了
深拷⻉
这个问题通常可以通过JSON.parse(JSON.stringify(object))来解决。

let a = {
 age: 1,
 jobs: {
 first: 'FE'
 } }
let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是该⽅法也是有局限性的:
会忽略undefined
会忽略symbol
不能序列化函数 不能解决循环引⽤的对象

let obj = {
 a: 1,
 b: {
 c: 2,
 d: 3,
 }, }
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)

深拷贝的实现:

ES6的Object.assign()方法

针对于对象只有一层的,不能实现真正的深拷贝。对象有多层的不能使用此方法。

Object.assign({},obj1)的意思是先建立一个空对象{},接着把obj1中所有的属性复制过去,所以obj2会长得跟obj1一样,这时候再修改obj2也不会影响obj1

var obj1 = {name:'lily'};
    var obj2 = Object.assign({},obj1);
    obj2.name = 'bob';
    console.log(obj1.name); //lily
    console.log(obj2.name); //bob

二:将对象转成字符串再转换回来

JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

 var obj = {
        a:'hello',
        b:{
            name:'lily',
            age:21
        },
        c:[1,2,3]
    };
    var obj1 = JSON.parse(JSON.stringify(obj));
    obj1.a = 'world';
    obj1.b = {
        name:'bob',
        age:15
    };
    obj1.c = [6,7,8];
    console.log(obj.a);
    console.log(obj.b);
    console.log(obj.c);
    console.log(obj1.aaa);
    console.log(obj1.bbb);
    console.log(obj1.ccc);

此时,即使改变了obj1里面每个属性的值,obj也不会受影响。但这种方法不能针对函数function,无效。

三:递归方法实现深拷贝

1:三元表达式:

表达式 (expr1) ? (expr2) : (expr3)

expr1求值为TRUE时的值为 expr2,在 expr1求值为 FALSE时的值为expr3。

2:hasOwnProperty():用来判断一个对象是否有自己的属性

function deepClone(obj){
        //先制造一个新的数组或对象,指向一个新的空间
        var newObj = Array.isArray(obj) ? [] : {};
        //判断obj的类型
        //基本类型
        if(typeof obj != 'object'){ //是普通类型的话就直接赋值,但不能直接返回obj,那样是浅拷贝
            return newObj = obj;
        }
        //引用类型
        if(obj instanceof Array){ //是数组
            for(var i=0;i<obj.length;i++){
                newObj[i] = obj[i];
                if(typeof newObj[i] == 'object'){ //如果数组的值有对象的话,就继续递归
                    deepClone(newObj[i]);
                }
            }
        }else{ //是对象
            for(var key in obj){
                if(obj.hasOwnProperty(key)){
                    if(typeof obj[key] == 'object'){ //对象中的数组和对象
                        newObj[key] = deepClone(obj[key]);  //继续递归
                    }else{//对象中没有引用类型
                        newObj[key] = obj[key];
                    }
                }
            }
        }
        return newObj;
    }
 
    var obj = {
        a:'haha',
        b:[1,2,3],
        c:function(){
            console.log('hello');
        }
    };
    var cloneObj = deepClone(obj);
    cloneObj.a = 'hello,word';
    cloneObj.b = [6,7,8];
    cloneObj.c = function(){
        console.log('world');
    };
    console.log(obj);
    console.log(cloneObj);
    

每天一句中文式外语

泰语

不明白!/mai-kao-zai 卖靠哉/ don't understand!

你能帮我一下吗?/kun-que-can-dai-mai坤鹊蚕代麦/ can you help me?

我在找。/can-ha-you 蚕哈友/ I'm looking for.

迷路了。/mai-lu-za-tan卖路杂摊/Lose way.

我想去 ---。/can-ya-bai蚕亚掰---/ I want to go to ---.

火车站/sha-tan-ni-luo-huai沙潭尼摞淮/ train station?

公共汽车站/sha-tan-ni-luo-mie 沙潭尼摞咩/Bus stop

飞机场/sha-nang-bing /沙囊冰/Air Station

酒店/long-liang /隆凉/Hotel

学校/long-lian/隆帘/school
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eugene.Tom.Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值