深拷贝和浅拷贝的区别(必须掌握)

前言:

在面试中,你必须要知道的一个知识点,那就是浅拷贝和深拷贝,那么就必须知道基本数据类型和引用类型,其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。

网片来自网络(侵删)
在这里插入图片描述

重点:你需要记住一句话:值类型传递的是值,引用类型传递的是地址

基本数据类型

这里就不做过多介绍了,基本数据类型值放在栈区,可直接访问与修改,且相互之间不会影响

引用类型

引用类型地址放在栈区,值放在堆区,所以当你进行赋值操作,其实赋值的是地址,所以二者之间是有关系的:

var obj1={
   name:'mengyun',
   age:18
};
var obj2 = obj1;
obj2.name = 'meimei';
console.log(obj1);//{name:'meimei',age:18}
console.log(obj2);//{name:'meimei',age:18}

可见是有联系的,而且曾经我一度以为赋值操作就是浅拷贝,其实不是的,还是太年轻~

下面看一个例子:

var obj1 = {
   name: 'mengyun',
    age: 18,
    hobby:{ play: [ 'footboll' ], read: 'book' },
    eat: ['苹果', '香蕉', '菠萝']
};

var obj2 = obj1;

function shallowCopy(target) {
    var result;
    if (Object.prototype.toString.call(target).slice(8, -1) === 'Object'){
        result={}
    }else if(Object.prototype.toString.call(target).slice(8, -1) === 'Array'){
        result=[]
    }
    for (var prop in target) {
        if (target.hasOwnProperty(prop)) {
            result[prop] = target[prop];
        }
    }
    return result;
}
var obj3 = shallowCopy(obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read= ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

结果如图:
在这里插入图片描述

因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。所以就会出现改变浅拷贝得到的 obj3 中的引用类型时,会使原始数据得到改变。而且浅拷贝可以修改第一层的引用类型

浅拷贝:

拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用

实现浅拷贝的方法:
  1. 手写一个浅拷贝
function shallowCopy(target) {
    var result;
    if (Object.prototype.toString.call(target).slice(8, -1) === 'Object'){
        result={}
    }else if(Object.prototype.toString.call(target).slice(8, -1) === 'Array'){
        result=[]
    }
    for (var prop in target) {
        if (target.hasOwnProperty(prop)) {
            result[prop] = target[prop];
        }
    }
    return result;
}
  1. Object.assign()
var obj1 = {
name: 'mengyun',
    age: 18,
    hobby: { play: ['footboll'], read: 'book' },
    eat: ['苹果', '香蕉', '菠萝'],
};

var obj2 = obj1;

var obj3 = Object.assign({}, obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read = ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

结果和上面一样

  1. 数组的浅拷贝
    展开运算符
var arr1=[1,2,3];
var arr2 = arr1;
arr2[1]='666';
console.log(arr1);//[1, "666", 3]
console.log(arr2);//[1, "666", 3]

var arr3 = [5,6,7];
var arr4 = [...arr3];
arr4[1]='666';
console.log(arr3);//[5,6,7]
console.log(arr4);//[5, "666", 7]

concat():

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

深拷贝:

把一个对象中所有的属性或者方法,一个一个的找到,并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中

实现深拷贝的方法:
  1. JSON.parse(JSON.stringify())
let obj1 = {
    a:3,
    b:4
}

let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
obj2.a = 5;
console.log(obj1);  //{a: 3, b: 4}
console.log(obj2);  //{a: 5, b: 4}
  1. 手写一个深拷贝(递归)
    法1:
function deepClone(target) {
    var result;
    if (Object.prototype.toString.call(target).slice(8, -1) === 'Object') {
        result = {}
    } else if (Object.prototype.toString.call(target).slice(8, -1) === 'Array') {
        result = []
    }else{
        return target
    }
    for (var prop in target) {
        if (target.hasOwnProperty(prop)) {
            result[prop] = deepClone(target[prop]);
        }
    }
    return result;
}

法2:

function deepClone(target) {
   if(typeof target !=='object' || target==null){
        //target是null,或者不是数组、对象,直接返回
        return target
    }
    let result;//初始化结果
    if(target instanceof Array){
        result = []
    }else{
        result = {}
    }
    for (var prop in target) {
        if(target.hasOwnProperty(prop)){//保证key不是原型上的属性
            result[prop] = deepClone(target[prop]);
        }
    }
    return result;
}

测试案例:

var obj1 = {
  name: 'mengyun',
   age: 18,
   hobby: { play: ['footboll'], read: 'book' },
   eat: ['苹果', '香蕉', '菠萝'],
};

var obj2 = obj1;

var obj3 = deepClone(obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read = ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

结果:
在这里插入图片描述

最后:

记住这张图
在这里插入图片描述
(图片侵删)

区别:

浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制

  • 12
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值