JavaScript中的浅复制、深复制的实现方式,区别基本数据类型和引用类型

数据类型

数据类型分为基本数据类型和引用数据类型

基本数据类型
  • 六种:Number(数值)、string(字符)、undefined、null、symbol、Boolean(布尔类型)

  • 存储位置:存放在栈中,使用完之后就会被销毁;数据大小确定,内存空间大小可以分配,它们是直接按值存放的,所以可以直接按值访问

  • eg:

    var a = 10;
    var b = a;
    b = 20;
    console.log(a); // 10值
    console.log(b); // 20值
    

    img

引用类型
  • 三种:object(对象)、array(数组)、function(函数);严格意义上就一种,即对象,因为数组函数都是对象

  • 存储位置:属性名存放在栈中,属性值存放在堆中,使用完之后不会销毁,而是垃圾回收机制将其回收

  • eg:

    var obj = {name:'yaxi'};
    var obj1 = obj;
    obj1.name = 'shuyan';
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KgDoPEut-1595855961175)(前复制以及深复制.assets/image-20200727210623804.png)]

浅复制

只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

特点

总结浅拷贝的规律:

​ 1、当第一层为基本数据类型时,改变不会使原始数据一同改变

​ 2、当原始数据中包含子对象时改变会时原数据一同改变

​ 3、既然属性值类型是数组和或象时只会传址

实现浅拷贝的方式
for…in
  • for…in只循环第一层

    let obj = {
        name: 'hong',
        arr: ['a', 'b', 'c'],
        'name': 'yaxi',
        obj1: {
            key: 'yaxi'
        }
    }
    
    function shalLowCopy(obj) {
        var newObj = Array.isArray(obj) ? [] : {};
        //for...in只循环第一层
        for (const i in obj) {
            if (obj.hasOwnProperty(i)) {
                newObj[i] = obj[i];
            }
        }
        return newObj;
    }
    
    let newObj = shalLowCopy(obj);
    console.log("----------------------------对象的浅复制----------------------------");
    console.log(newObj);
    newObj.arr[1] = '1';
    newObj.obj1.key = 'shuyan1';
    newObj.name = 'green';
    newObj.arr = ['1', '2'];
    newObj.obj1 = { key: 'shuyan2' }; //相当于在新对象中新建了一个与原始对象子对象同名的对象,所以在新对象中会使用新创建的子对象,但是对原始对象的子对象没有影响
    newObj.obj1.key = 'shuyan3';
    console.log(obj);
    console.log(newObj);
    
    //数组
    let arr = ['1', '2', '3', [
        '4', '5', '6'
    ]];
    let newArr = shalLowCopy(arr);
    console.log("----------------------------数组的浅复制----------------------------");
    console.log(newArr);
    newArr[2] = '4';
    newArr[3][1] = '10';
    console.log(arr);
    console.log(newArr);
    
object.assign()
  • 用es6中的方法object.assign()实现浅复制 特点:浅拷贝、对象属性的合并

    /**
     * var nObj = Object.assign({},obj,obj1);
     * 解析:花括号叫目标对象,后面的obj、obj1是源对象。
     * 对象合并是指:将源对象里面的属性添加到目标对象中去,若两者的属性名有冲突,后面的将会覆盖前面的
     */
    let newAssign = Array.isArray(obj) ? [] : {};
    Object.assign(newAssign, obj);
    console.log("----------------------------es6新方法object.assgin()的浅复制----------------------------");
    console.log(newAssign);
    newAssign.name = 'hongshuyan';
    newAssign.obj1.key = 'shuyan2';
    console.log(obj, newAssign)
    
深拷贝

通俗一点理解就是浅拷贝出来的数据并不独立,如果被复制的对象改变了,那么浅拷贝的对象也会改变,深拷贝之后就会完全独立,与浅拷贝断绝关系。

实现深拷贝的方法
使用for…in 用递归
  • 深拷贝:对象中所有子对象都会被遍历完全 方法一:使用for…in方法实现遍历和复制,其中子对象使用递归
function shalHighCopy(obj) {
    let newObj = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj === 'object') {
        for (let i in obj) {
            if (obj.hasOwnProperty(i)) {
                if (obj[i] && typeof(obj[i]) === 'object') {
                    //如果对象的属性值为object的时候,递归调用shalHighCopy,即再把子对象复制一份到新的对象的对应值中。
                    newObj[i] = shalHighCopy(obj[i]);
                } else {
                    newObj[i] = obj[i];
                }
            }
        }
        return newObj;
    }
    return obj;
}

let newObj2 = shalHighCopy(obj);
console.log("----------------------------使用for...in方法 递归实现深复制----------------------------");
console.log(newObj2);
newObj2.arr[1] = '0';
newObj2.obj1.key = 'shuyan4';
console.log(obj);
console.log(newObj2);

使用json方法实现
  • 方法二:使用json方法实现
function jsonCopy(obj) {
    let _temp = JSON.stringify(obj); //将对象转化为字符串形式
    let temp = JSON.parse(_temp); //将字符串转化为对象
    return temp;
}
let newObj3 = shalHighCopy(obj);
console.log("----------------------------使用json方法实现深复制----------------------------");
console.log(newObj3);
newObj3.arr[2] = '2';
newObj3.obj1.key = 'shuyan5';
console.log(obj);
console.log(newObj3);

Array.prototype.forEach
  • 方法三:利用数组的Array.prototype.forEach进copy

    let deepClone = function(obj) {
        let copy = Object.create(Object.getPrototypeOf(obj));
        let propNames = Object.getOwnPropertyNames(obj);
        propNames.forEach(function(items) {
            let item = Object.getOwnPropertyDescriptor(obj, items);
            Object.defineProperty(copy, items, item);
    
        });
        return copy;
    };
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值