最简单的深拷贝和浅拷贝(原理)

拷贝:其实就是一个对象复制给另外一整个对象,让对象相互不影响。

对象的拷贝又分为浅拷贝和深拷贝

对象的浅拷贝:浅拷贝是指只复制对象的第一层属性,如果对象的属性值是引用类型(如对象、数组等),则复制的是引用,而不是真正的拷贝。

对象的深拷贝:深拷贝是指在复制对象时,不仅复制对象本身,还递归地复制对象所有的属性,直到所有属性都是基本数据类型(如字符串、数字、布尔值等),而不是简单地复制对象的引用。这样就可以确保复制后的对象与原始对象完全独立,互不影响。

注意:浅拷贝和深拷贝只针对object和Array这样的复杂的对象

一.浅拷贝Object.assign()

Object.assign() 方法用于将一个或多个源对象的可枚举属性复制到目标对象,并返回目标对象。它实现了浅拷贝的功能。

 

 1 // (1)用来复制一个新对象,并不会影响原对象
 2     let object = {
 3         a : 1
 4     }
 5     let empty = {}
 6     empty = Object.assign(empty,object)
 7     console.log(`object:${JSON.stringify(object)};empty:${JSON.stringify(empty)}`) //object:{"a":1};empty:{"a":1}
 8     
 9     //(2)用来合并对象属性,将源对象的所有可枚举属性,复制到目标对象。
10     let obj = {
11         name : "jack",
12         age : '18'
13     }
14     let obj2 = {
15         work : 'lawyer'
16     }
17     obj2 = Object.assign(obj2,obj)
18     console.log(`obj:${JSON.stringify(obj)};obj2:${JSON.stringify(obj2)}`) //obj:{"name":"jack","age":"18"};obj2:{"work":"lawyer","name":"jack","age":"18"}
19 
20     // (3)如果目标对象和源对象中有相同的键,则属性将被源对象的属性覆盖,后面的源属性会覆盖之前的相同键的源属性。
21     let red ={
22         name : "小红包",
23         age : '20'
24     }
25     let blue = {
26         name : '小兰'
27     }
28     blue = Object.assign(blue,red)
29     console.log(`red:${JSON.stringify(red)};blue:${JSON.stringify(blue)}`)//red:{"name":"小红包","age":"20"};blue:{"name":"小红包","age":"20"}
30     let green = {
31         name : '小吕'
32     }
33     blue = Object.assign(blue,red,green)
34     console.log(`red:${JSON.stringify(red)};blue:${JSON.stringify(blue)};green:${JSON.stringify(green)}`)//red:{"name":"小红包","age":"20"};blue:{"name":"小吕","age":"20"};green:{"name":"小吕"}
35 
36     // (4)当assign只有一个对象时,则直接返回这个对象,不做任何操作;
37     let quondam = {
38         a : 'self'
39     }
40     Object.assign(quondam)
41     console.log(quondam) //{a: 'self'}
42 
43     // (5)Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
44     //当我们在改变person的值时,并没有想改变other,但other的值也发生了改变,这违背了我们的想法。
45     let person = {
46         name : '杨幂',
47         age : '16',
48         works : {
49             video : '宫'  ,
50             musinc : '爱的供养'
51         }
52     }
53     let other = {}
54     other = Object.assign(other,person)
55     console.log(`other:${JSON.stringify(other)}`) //other:{"name":"杨幂","age":"16","works":{"video":"宫","musinc":"爱的供养"}}
56 
57     person.works.video = '三生三世'
58     console.log(`person:${JSON.stringify(person)};other:${JSON.stringify(other)}`)//person:{"name":"杨幂","age":"16","works":{"video":"三生三世","musinc":"爱的供养"}};other:{"name":"杨幂","age":"16","works":{"video":"三生三世","musinc":"爱的供养"}}
59 
60     //(6)给当前的对象添加新的属性
61     const static = {
62         name :'静态对象'
63     }
64     Object.assign(static,{type:'添加属性'})
65     console.log(static) //{name: '静态对象', type: '添加属性'}

 

 

 

Object.assign() 方法的原理如下:

1.首先,创建一个新的空对象作为目标对象。

2.然后,依次遍历源对象的所有可枚举属性,并将这些属性复制到目标对象中。

3.如果源对象的属性值是基本数据类型(如字符串、数字、布尔值等),则直接将其复制到目标对象中。

4.如果源对象的属性值是引用类型(如对象、数组等),则复制的是引用,即目标对象中的属性与源对象中的属性指向同一个引用。

 

总的来说,Object.assign() 方法提供了一种简单且常用的浅拷贝对象的方法,但需要注意引用类型复制的特性以及对属性的覆盖情况。如果需要进行深拷贝,可以使用其他更全面的方法来确保正确性和完整性。

 

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

JSON.parse(JSON.stringify()) 是一种常用的实现深拷贝的方法,它的原理是利用 JSON 的序列化和反序列化过程。

 

 1 let star = {
 2         name :'成毅',
 3         age : '30',
 4         works : {
 5             video : '莲花楼',
 6             music : '江湖之上'
 7         }
 8     }
 9     let lian = { }
10 
11     lian = JSON.parse(JSON.stringify(star))
12     console.log(`star:${JSON.stringify(star)};lian:${JSON.stringify(lian)}`) //star:{"name":"成毅","age":"30","works":{"video":"莲花楼","music":"江湖之上"}};lian:{"name":"成毅","age":"30","works":{"video":"莲花楼","music":"江湖之上"}}
13     star.works.video = '沉香如屑'
14     console.log(`star:${JSON.stringify(star)};lian:${JSON.stringify(lian)}`) //star:{"name":"成毅","age":"30","works":{"video":"沉香如屑","music":"江湖之上"}};lian:{"name":"成毅","age":"30","works":{"video":"莲花楼","music":"江湖之上"}}

 

原理:

1.JSON.stringify():这个方法将一个 JavaScript 对象转换为一个 JSON 字符串。在这个过程中,所有可以被 JSON 格式表示的数据类型(如字符串、数字、布尔值、数组、对象等)都会被正确地转换为对应的 JSON 格式。

2.JSON.parse():这个方法将一个 JSON 字符串解析为一个 JavaScript 对象。在这个过程中,JSON 字符串会被解析为对应的 JavaScript 数据类型。

3.因此,当我们使用 JSON.stringify() 将一个对象进行序列化(转换为 JSON 字符串),然后再使用 JSON.parse() 将该 JSON 字符串进行反序列化(转换为 JavaScript 对象)时,就可以得到原始对象的一个深拷贝

4.需要注意的是,使用 JSON.stringify()JSON.parse() 进行深拷贝的方法有一些限制:只能拷贝能够被 JSON 表示的数据类型,例如函数、正则表达式等无法被正确拷贝;只能拷贝能够被 JSON 表示的数据类型,例如函数、正则表达式等无法被正确拷贝。

 

总的来说,JSON.parse(JSON.stringify()) 方法是一种简单且常用的实现深拷贝的方法,但需要注意上述的限制条件。对于复杂对象或包含特殊数据类型的对象,可能需要使用其他更全面的深拷贝方法来确保正确性和完整性。

 

 1  // 封装深拷贝
 2     function deepClone(data) {
 3 
 4         let register = data.constructor === Array ? [] : {};
 5 
 6         for (let key in data) {
 7             if (data.hasOwnProperty(key)) {
 8                 if (data[key] && typeof (data[key]) == 'object') {
 9                     register[key] = data[key].constructor === Array ? [] : {};
10                     register[key] = deepClone(data[key])
11                 } else {
12                     register[key] = data[key]
13                 }
14             }
15 
16         }
17 
18         return register
19     }
20 
21 
22     let newStar = deepClone(star)
23     newStar.age = '34'
24     newStar.works.video = '狐妖小红娘'
25     console.log(star,newStar)

 

posted on 2024-02-21 16:33  萬事順意  阅读(22)  评论(0编辑  收藏  举报