JavaScript中浅拷贝与深拷贝的概念及区别

目录

一、浅拷贝(shallow copy)

二、深拷贝(deep copy)

三、拷贝方法

1.通过 Object.assign() 拷贝(一深二浅)

2.通过slice()和concat()拷贝(浅拷贝)

3.JSON.parse(JSON.stringify())(深拷贝)


一、浅拷贝(shallow copy)

浅拷贝是按位拷贝对象, 它会创建一个新对象 ,这个对象有着原始对象属性值的一份精确拷贝。 如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存。

浅拷贝是指对基本类型的值拷贝,以及对对象类型的地址拷贝。

//对基本类型(值拷贝)
var a = 1; //number 基本类型,string、Boolean
var b = a; //浅拷贝 - 值拷贝
b = 2; //改变b的值,并不会影响到a,因为浅拷贝对基本类型而言就是值拷贝
console.log(a); //a=1

//对对象类型(地址拷贝)
var p1 = { //对象类型
    name:'jack'
    age:12
}
var p2 = p1; //地址拷贝
p2.age = 20; //改变p2的值,会影响到p1,因为浅拷贝对对象类型会进行地址拷贝
console.log(p1.age) //p1.age = 20

实现:浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用(地址),所以改变新对象,旧对象也会改变,因为新旧对象共享一块内存。

二、深拷贝(deep copy)

深拷贝是指复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

三、拷贝方法

1.通过 Object.assign() 拷贝(一深二浅)

Object.assign(目标文件, 原文件) 是一种可以对非嵌套对象进行深拷贝的方法,如果对象中出现嵌套情况,那么其对被嵌套对象的行为就变成了普通的浅拷贝。

var p1 = { //对象类型
    name:'jack'
    age:12
    toy:{ //嵌套对象类型
        name: 'car'
    }
}

var p2 = {}
object.assign(p2,p1)
p2.age = 20
console.log(p1.age) //p1.age = 12 //嵌套对象外的拷贝对象类型属于深拷贝

p2.toy.name = plane
console.log(p1.toy.name) //p1.toy.name = plane嵌套对象中的拷贝对象类型属于浅拷贝

注意:

  • 当对象只有一级属性为深拷贝;
  • 当对象中有多级属性时,二级属性后就是浅拷贝;

2.通过slice()和concat()拷贝(浅拷贝)

slice(begin,end):返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end).原数组元素不变

//Array.prototype.slice()
let arr = [1, 3, {
    username: ' kobe'
    }];
let arr2 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); //arr[2] = 'wade'修改新对象会改到原对象

concat(array):合并两个新数组。原数组不变

//Array.prototype.concat()
let arr = [1, 3, {
    username: 'kobe'
    }];
let arr3=arr.concat();    
arr2[2].username = 'wade';
console.log(arr); //arr[2] = 'wade'同样修改新对象会改到原对象

关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

3.JSON.parse(JSON.stringify())(深拷贝)

 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

let arr = [1, 3, {
    username: ' kobe'
}];

let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'wade';
 
console.log(arr, arr4) 
//arr[2] = 'kobe' //原对象类型未修改
//arr4[2] = 'wade'

注意:这种方法可以实现数组或对象深拷贝,但不能处理函数

参考文章:

[1] 浪里行舟.《浅拷贝与深拷贝》,知乎,2018.12.23

[2]JavaScript百炼成仙.《聊聊JavaScript深拷贝和浅拷贝》.Bilibili.2022.3.9

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值