deep clone and shadow clone 2.0

看一段代码

		let obj = {
            name: '张三',
            child: {
                age: 23
            }
        }
        let obj2 = obj;
        console.log(obj); //{'张三'}
        obj2.name = "李四";
        console.log(obj); //{'李四'}

那我把它的值复制不就行了吗,再来一段代码

let obj = {
            name: '张三',
            child: {
                age: 23
            }
        }
        let obj2 = {};

        Object.keys(obj).forEach(key => {
            obj2[key] = obj[key];
        })
        obj2.name = '李四'
        obj2.child.age = 21;
        console.log(obj); // 张三 21

你会发现子对象修改源对象也进行了修改
这就是浅拷贝本质。在深一点的本质就是栈与堆内存的使用。
优化一下:

function shadowClone(sourceObj) {
            let targetObj = Array.isArray(sourceObj) ? [] : {}; //数组还是对象
            Object.keys(sourceObj).forEach(key => {
                targetObj[key] = sourceObj[key];
            })
            return targetObj;
        }

那我递归把子对象值也复制一遍那不就行了,这就是深拷贝的由来。

function deepClone(sourceObj) {
            let targetObj = Array.isArray(sourceObj) ? [] : {};
            Object.keys(sourceObj).forEach(key => {
                let value = sourceObj[key];
                if (typeof(value) === 'object') {
                    if (value instanceof Object) { //一位老哥的写法 原型链我还没看----存疑
                        targetObj[key] = deepClone(value);
                    } else {
                        targetObj[key] = sourceObj[key];
                    }

                } else if (typeof(value) === 'function') {
                    targetObj[key] = eval(value.toString()) //安全性问题
                } else {
                    targetObj[key] = sourceObj[key];
                }
            })
            return targetObj;
        }
        let obj2 = deepClone(obj);
        console.log(obj2);
        obj2.child.age = 21
        console.log(obj.child); //{23}

其他方法:

  • contact /slice
let arr = [1, 2, 3, [1, 4, 5]]
        let arr2 = [].concat(arr);
        console.log(arr2);
        arr2[3][0] = 2
        console.log(arr); //[1, 2, 3, [2, 4, 5]]

但是:一层可以深拷贝,如果是多层或是对象只能浅拷贝,slice同理。

  • Object.assign/create

Object.assign(target, …sources)

用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。

		let obj = {
            name: '张三',
            child: {
                age: 23
            }
        }
		let tar = {}
        Object.assign(tar, obj);
        console.log(tar);
        tar.name = '李四';
        tar.child.age = 21;
        console.log(obj); //张三 21

所以说还是一层深拷贝。create也是。
注意:
Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象
继承和不可枚举属性不会拷贝

  • es6 中解构也是一层

  • JSON.parse()

用 JSON.stringify() 把对象转成字符串,再用 JSON.parse() 把字符串转成新的对象,可以实现对象的深复制。

  		let obj2 = JSON.parse(JSON.stringify(obj))
        obj2.child.age = 21;
        console.log(obj); //23

but :
look at this

let obj = {
                name: '张三',
                child: {
                    age: 23
                },
                x: function() {

                }
            }
  1. 它复制不了函数
  2. 能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp 对象是无法通过这种方式深拷贝。
  3. 深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成 Object;深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成 Object;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值