文章类型:个人学习笔记

前言

友情提醒:个人学习笔记,可能有写的不对的地方,还请大佬们发现了提醒一下小弟我。

1.浅拷贝

定义:一个对象直接拷贝已存在对象的属性的引用。

还没开始讲这篇文章的时候,让你自己去写一个拷贝,你会怎么写?

(1)直接赋值

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer'
        }
        let obj1 = obj;
        console.log(obj1 === obj); // true

(2)借助 ES6 的 Object.assign() 方法实现一个浅拷贝

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer'
        }
        let obj1 = Object.assign({}, obj);
        console.log(obj1 === obj); // false
        obj1.age = 10;
        console.log(obj.age); // 20
        console.log(obj1.age); // 10

我们会发现,当对象内部属性全部为基础类型时,改变新拷贝的对象属性值,并不会影响到原对象,换句话说,如果你的对象里都是基础类型,你想对他进行拷贝,使用浅拷贝即可。

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer',
            friends: ['小花', '小丽']
        }
        let obj1 = Object.assign({}, obj);
        console.log(obj1 === obj); // false
        obj1.friends[1] = '小萌';
        console.log(obj.friends); // ["小花", "小萌"]
        console.log(obj1.friends); // ["小花", "小萌"]

当原对象中有属性时引用类型时,我们会发现改变新拷贝的引用类型属性值时,原对象的引用类型属性值也发生了改变,这就是拷贝的不够彻底,所以我们就需要深拷贝。

(3)借助 ES6 的展开语法实现浅拷贝

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer',
            friends: ['小花', '小丽']
        }
        let obj1 = { ...obj };
        console.log(obj1 === obj);
        obj1.age = 10;
        obj.friends[0] = '小美';
        console.log(obj.age); // 20
        console.log(obj1.age); // 10
        console.log(obj.friends); // ["小美", "小丽"]
        console.log(obj1.friends); // ["小美", "小丽"]

(4)遍历赋值的方法实现浅拷贝

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer',
            friends: ['小花', '小丽']
        }
        let obj1 = {};
        for (const item of Object.entries(obj)) {
            obj1[item[0]] = item[1];
        }
        console.log(obj1 === obj);
        obj1.age = 10;
        obj.friends[0] = '小美';
        console.log(obj.age); // 20
        console.log(obj1.age); // 10
        console.log(obj.friends); // ["小美", "小丽"]
        console.log(obj1.friends); // ["小美", "小丽"]

2.深拷贝

复制一个一模一样的对象,不共享内存,修改一个对象,不会影响到另一个对象

(1)利用JSON.stringify()

        let obj = {
            name: '小明',
            age: 20,
            job: 'Software Engineer',
            friends: ['小花', '小丽']
        }
        let obj1 = JSON.parse(JSON.stringify(obj));
        obj1.friends[0] = '小美';
        console.log(obj.friends); // ["小花", "小丽"]
        console.log(obj1.friends); // ["小美", "小丽"]

缺陷:处理不了function对象、undefined以及symbol类型,原因时JSON.stringify()在处理这些类型,这些类型会被忽略,不会被处理,详情见 MDN

(2)递归,对每层数据实行遍历然后进行拷贝

        let obj = {
            name: {
                firstName: '小',
                lastName: '星',
            },
            age: 25,
            arr: [{ a: 10 }, { b: 50 }]
        }
        function copyObj(obj) {
            let obj1 = Array.isArray(obj) ? [] : {};
            for (const key in obj) {
                if (typeof obj[key] === 'object') {
                    obj1[key] = copyObj(obj[key]);
                } else {
                    obj1[key] = obj[key]
                }
            }
            return obj1
        }
        let obj2 = copyObj(obj);
        obj2.arr[0].a = 80;
        obj2.name.firstName = '王';
        console.log(obj);
        console.log(obj2);

(3)Jquery中实现深拷贝

Jquery中实现深拷贝的原理也是递归

        let obj = {
            name: {
                firstName: '小',
                lastName: '星',
            },
            age: 25,
            sayName() { }
        }
        let obj2 = $.extend(true, {}, obj);
        obj2.name.firstName = '王';
        console.log(obj.name.firstName); // 小
        console.log(obj2.name.firstName); // 王

(4)Lodash中的 _.defaultsDeep() 方法

        let obj = {
            name: {
                firstName: '小',
                lastName: '星',
            },
            age: 25,
            arr: [{ a: 10 }, { b: 50 }]
        }
        let obj2 = _.defaultsDeep({}, obj);
        obj2.arr[0].a = 80;
        obj2.name.firstName = '王';
        console.log(obj);
        console.log(obj2);