JavaScript对象的深拷贝和浅拷贝总结-创新互联

这篇文章主要介绍“JavaScript对象的深拷贝和浅拷贝总结”,在日常操作中,相信很多人在JavaScript对象的深拷贝和浅拷贝总结问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript对象的深拷贝和浅拷贝总结”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

创新互联成都网站建设按需网站开发,是成都网站制作公司,为成都航空箱提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站建设热线:028-86922220

什么是对象的拷贝?

将一个对象赋值给另外一个对象, 我们称之为对象的拷贝。

什么是深拷贝, 什么是浅拷贝?

我们假设将A对象赋值给B对象。浅拷贝是指, 修改B对象的属性和方法会影响到A对象的属性和方法, 我们称之为浅拷贝

以下两种情况都属于浅拷贝:

1、默认情况下对象之间的 直接赋值 都是浅拷贝。

let A = {

name: 'zyx',

age: 20

}

let B = A

console.log(B) // {name: "zyx", age: 20}

//修改B的 name 属性

B.name = 'ls'

//A 也收到影响

console.log(A) // {name: "ls", age: 20}

console.log(B) // {name: "ls", age: 20}

赋值操作(包括对象作为参数、返回值),不会开辟新的内存空间,他只是赋值了对象的引用.也就是除了B这个名字之外,没有其他的内存开销,修改了A也就影响了B,修改了B,也就影响了A.

2、如果 对象的属性包含了引用数据类型(数组、对象) ,那么哪怕不是直接赋值操作,而是开辟了一层新的内存空间,也就是说只拷贝了A对象的一层,这仍然属于浅拷贝。

let A = {

name: 'ls',

age: 20,

hobbies: ['dance','basketball','read'],

dogs:{

name: '大黄',

color: 'yellow'

}

}

let B = {}

//定义一个函数,把A对象的属性复制一份给B

function extend(obj1,obj2){

for(var key in obj1){

obj2[key] = obj1[key]

}

}

extend(A,B)

//修改B对象中的引用类型数据 ,A对象也收到影响

B.dogs.color = 'red'

B.hobbies[0] = 'sing'

console.log(B)

console.log(A)

修改B对象中的引用类型数据 ,A对象也收到影响,属于浅拷贝。

3、ES6中新增的 Object.assign() 也是对象的浅拷贝

Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。 Object.assign 方法的第一个参数是目标对象,后面的参数都是源对象。 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

const obj1 = {a: {b: 1}};

const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;

obj2.a.b // 2

上面代码中,源对象 obj1 的 a 属性的值是一个对象, Object.assign 拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

4、扩展运算符(...)

利用扩展运算符可以在构造字面量对象时,进行克隆或者属性拷贝 ,属于浅拷贝。

var obj = {a:1,b:{c:1}}

var obj2 = {...obj};

obj.a=2;

console.log(obj); //{a:2,b:{c:1}}

console.log(obj2); //{a:1,b:{c:1}}

obj.b.c = 2;

console.log(obj); //{a:2,b:{c:2}}

console.log(obj2); //{a:1,b:{c:2}}

5、Array.prototype.slice()

slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。

深拷贝是指, 修改B对象的属性和方法不会影响到A对象的属性和方法, 我们称之为深拷贝。

以下两种情况都属于深拷贝:

5.1、默认情况下一个 对象的属性如果是基本数据类型 , 那么进行复制(拷贝),都是深拷贝。

如果A对象的属性都是基本数据类型(Number、String等),此时要想深拷贝一份A给B,该怎么做呢,在这种 要拷贝的对象A只有基本类型的数据时 ,只需要在内存中开辟一块空间存储B就行了。

let A = {

name: 'zyx',

age: 20

}

let B = {}

//定义一个函数,把A对象的属性复制一份给B

function extend(obj1,obj2){

for(var key in obj1){

obj2[key] = obj1[key]

}

}

extend(A,B)

console.log(B) // {name: "zyx", age: 20}

B.name = 'ls'

console.log(B) // {name: "ls", age: 20}

console.log(A) // {name: "zyx", age: 20}

这样就实现了深拷贝。

5.2、如果 要拷贝的对象本身又包含了引用数据类型 ,即对象又包含数组或者对象,层层嵌套的情况下,想要实现对象的深拷贝,可以采用 递归 的方式进行深拷贝。

let A = {

name: 'ls',

age: 20,

hobbies: ['dance','basketball','read'],

dogs:{

name: '大黄',

color: 'yellow'

}

}

let B = {}

//定义一个函数,把A对象的属性复制一份给B

function extend(obj1,obj2){

for(var key in obj1){

var item = obj1[key]

if(item instanceof Array){

obj2[key] = []

extend(item,obj2[key])

}else if(item instanceof Object){

obj2[key] = {}

extend(item,obj2[key])

}else{

obj2[key] = item

}

}

}

extend(A,B)

B.dogs.color = 'red'

B.hobbies[0] = 'sing'

console.log(B)

console.log(A)

运行发现,修改B对象的引用数据类型,不会影响到A对象,完成深拷贝。

我们可以对深拷贝的代码进行封装优化

function deepClone(obj){

let cloneObj = {}

for(let key in obj){

if(typeof obj[key] === 'object'){

cloneObj[key] = deepClone(obj[key])

}else{

cloneObj[key] = obj[key]

}

}

return cloneObj

}

5.3、通过JSON.stringify实现深拷贝。

JSON.stringify()是目前前端开发过程中最常用的深拷贝方式,原理是把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象。

var obj1 = {

a:1,

b:[1,2,3]

}

var str = JSON.stringify(obj1)

var obj2 = JSON.parse(str)

console.log(obj2); //{a:1,b:[1,2,3]}

obj1.a=2

obj1.b.push(4);

console.log(obj1); //{a:2,b:[1,2,3,4]}

console.log(obj2); //{a:1,b:[1,2,3]}

到此,关于“JavaScript对象的深拷贝和浅拷贝总结”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


标题名称:JavaScript对象的深拷贝和浅拷贝总结-创新互联
网站URL:http://myzitong.com/article/dggooo.html