JS 浅拷贝和深拷贝详解(巨详细)

目录

一、前置知识详解

1.1.JavaScript数据类型

1.2.理解传值和传址

二、浅拷贝

2.1.浅拷贝的定义和原理

2.2.实现浅拷贝的方法

2.2.1.手写递归实现

2.2.2.利用展开语法实现浅拷贝

 2.2.3.Object.assign进行对象的合并

2.2.4.利用Array.prototype.,slice()

2.2.5.利用Array.prototype.contact()

三、深拷贝

3.1.深拷贝的定义及原理

3.2.深拷贝的实现方法

3.2.1.递归实现深拷贝

3.2.2.JSON.parse(JSON.stringify(待拷贝对象)

 3.2.3.jQuery 中的 $.extend() 第一个参数设置为true为深拷贝,为false为浅拷贝(要引入JQuery库)

3.2.4.引入loadsh,提供 cloneDeep 实现


一、前置知识详解

在学习浅拷贝和深拷贝之前,我们有必要了解的前置知识

1.1.JavaScript数据类型

JavaScript的数据类型分为基本类型:Number,String,Boolean,Undefined,Null,Symbol,BigInt

                                          引用l类型:对象(Object),数组(Array),函数(Function)

基本类型数据保存在在栈内存中

引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中

1.2.理解传值和传址

传值:开辟新内存区域存储值

代码示例如下

            let a = 3;
            let b = a;
            console.log(a, b);  // 3 3
            b = 5;  
            console.log(a, b);  // 3 5

传址:传递内存地址,而不开辟新空间

            let obj = {
                name: 'zs',
                age: 20,
            };
            let obj1 = obj;
            console.log(obj, obj1);
            obj1.name = 'lisi';
            console.log(obj, obj1);

 

输出内容相同,obj和obj1指向了同一个内存地址。

二、浅拷贝

2.1.浅拷贝的定义和原理

浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址

2.2.实现浅拷贝的方法

2.2.1.手写递归实现

            // 手写实现浅拷贝
            function shallowClone(obj) {
                let newObj = {};
                for (let i in obj) {
                    // 只要是obj的属性,直接复制一份给newObj
                    if (obj.hasOwnProperty(i)) {
                        newObj[i] = obj[i];
                    }
                }
                return newObj;
            }
            const person = {
                name: 'zs',
                hobby: ['排球', '网球', '篮球'],
            };
            const person1 = shallowClone(person);
            console.log(person);
            console.log(person1);
            person1.name = 'lisi';
            person1.hobby[0] = '足球';
            console.log(person);
            console.log(person1);

打印输出结果如下

2.2.2.利用展开语法实现浅拷贝

            let obj = {
                name: 'zs',
                lessons: ['hobby', 'suxexu', 'kligh'],
            };
            let hd1 = { ...obj };
            hd1.name = 'lisi';
            hd1.lessons[0] = 'math';
            console.log(obj);
            console.log(hd1);

 2.2.3.Object.assign进行对象的合并

            let obj = {
                name: 'zs',
                lessons: ['hobby', 'suxexu', 'kligh'],
            };
            let newObj = Object.assign({}, obj);
            newObj.lessons[0] = 'math';
            console.log(obj);
            console.log(newObj);

2.2.4.利用Array.prototype.,slice()

            const arr = [1, 2, { name: 'nordon' }];
            const newArr = arr.slice();
            newArr[2].name = 'wy';
            console.log(arr);
            console.log(newArr);

2.2.5.利用Array.prototype.contact()

            const arr = [1, 2, { name: 'nordon' }];
            const newArr = arr.concat();
            newArr[2].name = 'wy';
            console.log(arr);
            console.log(newArr); 

三、深拷贝

3.1.深拷贝的定义及原理

  深拷贝开辟一个新的栈,两个对象属性完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

3.2.深拷贝的实现方法

3.2.1.递归实现深拷贝

第一种方法

            function deepClone(obj) {
                let newObj = obj instanceof Array ? [] : {};
                for (let i in obj) {
                    if (obj.hasOwnProperty(i)) {
                        if (obj[i] && typeof obj[i] == 'object') {
                            // 若对象属性还是引用类型,进行递归
                            newObj[i] = deepClone(obj[i]);
                        } else {
                            // 对象属性为基础数据类型,直接赋值
                            newObj[i] = obj[i];
                        }
                    }
                }
                return newObj;
            }
            const obj = {
                name: 'zs',
                hobby: ['排球', '网球', '乒乓球'],
            };
            const newObj = deepClone(obj);
            newObj.name = 'lisi';
            newObj.hobby[0] = '篮球';
            console.log(obj);
            console.log(newObj);

第二种方法,巧妙运用Object.entries(obj)遍历对象的属性和值

            function deepClone(obj) {
                let newObj = obj instanceof Array ? [] : {};
                for (const [k, v] of Object.entries(obj)) {
                    newObj[k] = typeof v == 'object' ? deepClone(v) : v;
                }
                return newObj;
            }
            const obj = {
                name: 'zs',
                hobby: ['排球', '网球', '乒乓球'],
            };
            const newObj = deepClone(obj);
            newObj.name = 'lisi';
            newObj.hobby[0] = '篮球';
            console.log(obj);
            console.log(newObj);

输出结果相同,如下:

3.2.2.JSON.parse(JSON.stringify(待拷贝对象)

            const obj = {
                name: 'zs',
                hobby: ['排球', '网球', '乒乓球'],
            };
            const newObj = JSON.parse(JSON.stringify(obj));
            newObj.name = 'lisi';
            newObj.hobby[0] = '篮球';
            console.log(obj);
            console.log(newObj);

 3.2.3.jQuery 中的 $.extend() 第一个参数设置为true为深拷贝,为false为浅拷贝(要引入JQuery库)

            const obj1 = {
                a: 1,
                b: { f: { g: 1 } },
                c: [1, 2, 3],
            };
            const obj2 = $.extend(true, {}, obj1);
            console.log(obj1.b.f === obj2.b.f);

3.2.4.引入loadsh,提供 cloneDeep 实现

vue中使用loash库实现深拷贝的步骤

  1. 安装loadsh    npm i --save lodash
  2. 引入loadsh    import _ from 'lodash'
  3. 直接调用loadsh库的方法 const newObj = _.cloneDeep(this.obj)

  • 14
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
深拷贝浅拷贝是在对象复制过程中常用的两种方式,它们的区别在于复制后的对象与原始对象之间的关系。 浅拷贝(Shallow Copy)是创建一个新对象,该对象与原始对象的元素是对原始对象中元素的引用。换言之,复制后的对象与原始对象共享内部对象的引用。当修改原始对象中的可变元素时,这些修改也会反映在复制后的对象中。 深拷贝(Deep Copy)则是创建一个全新的独立对象,复制后的对象与原始对象完全独立,互不影响。深拷贝会递归地复制原始对象及其内部所有可变对象,而不仅仅是引用。 举个例子来说明: ```python import copy # 原始对象 original_list = [1, 2, [3, 4]] # 浅拷贝 shallow_copy = copy.copy(original_list) # 深拷贝 deep_copy = copy.deepcopy(original_list) # 修改原始对象中的可变元素 original_list[0] = 10 original_list[2].append(5) print(original_list) # 输出: [10, 2, [3, 4, 5]] print(shallow_copy) # 输出: [10, 2, [3, 4, 5]] print(deep_copy) # 输出: [1, 2, [3, 4]] ``` 在上面的例子中,原始对象是一个列表 `original_list`,其中包含一个整数和一个列表。通过浅拷贝 `copy.copy()` 和深拷贝 `copy.deepcopy()` 分别创建了复制对象 `shallow_copy` 和 `deep_copy`。 当我们修改原始对象的第一个元素和第三个元素的子列表时,可以看到浅拷贝对象也受到了影响,而深拷贝对象保持不变。 因此,在需要创建独立的对象副本且避免修改原始对象时,深拷贝是更安全和可靠的选择,而浅拷贝则更适合在一些特定场景下节省内存或共享数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

~black-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值