前端经典⾯试题:深拷贝和浅拷贝
⼀、写在前⾯
在任何编程语⾔中,都存在和浅拷贝的概念,js当然也不例外。在对⼀个现有对象进⾏拷贝的时候是有深拷贝和浅拷贝之说的,他们在实际使⽤中区别还是挺⼤的,如果不弄清原因,可能在⼯作中遇到错误不好排查。
⼆、什么是深拷贝和
⾸先需要明⽩的⼀点是:深拷贝和浅拷贝针对的是对象进⾏操作的。那么就先来看看深拷贝和浅拷贝的具体概念。在js中,除了基本数据类型以外,还存在引⽤数据类型。⽽在⼀般使⽤赋值语句=的时候。对于基本数据类型,实际上只是拷贝它的值,但是对于对象⽽⾔,其实赋值的是这个对象的内存引⽤(内存地址),将原来对象的引⽤传递过去,实际上新对象和旧对象使⽤的是同⼀个内存引⽤(地址)。
⽽深拷贝和浅拷贝就是在这个基础上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进⾏了拷贝,⽽对引⽤数据类型只是做了引⽤的传递,⽽没有重新开辟⼀个内存空间存放这个对象,则认为是浅拷贝。反之,在对引⽤数据类型进⾏拷贝的时候,创建了⼀个新的对象(开辟新的内存空间),并且复制其内的变量,则认为是深拷贝。
所以到现在,就应该了解,所谓的深拷贝和浅拷贝,只是在拷贝对象的时候,在其中引⽤类型变量的不同操作(是否为其开辟新的内存空间)⽽已。
三、js 如何实现深拷贝和浅拷贝
由于浅拷贝⽐较容易实现,所以从易到难开始介绍:
1. 浅拷贝 现在的需求是把变量obj拷贝给’o’  let  obj = {    name : 'lwf',    age : 18,    color : ['红⾊', '蓝⾊'],    like : {      game : '玩游戏',      sport : '打乒乓'    }  }  let  o = {}//浅拷贝  copy  = (newObj , oldObj ) => {    for  (let  k in  oldObj ) {      newObj [k ] = oldObj [k ]    }  }  copy (o , obj )  o .name = 'cll'  o .color .push ('绿⾊')  console .log (o );  console .log (obj );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
复制以后修改o的两个属性包括基本数据类型的name
,引⽤数据类型的color,输出结果如下:在obj的引⽤数据类型color 属性更改了,name 属性没更改,相当于是实现了浅拷贝。
在js中还有⼀个原⽣实现浅拷贝的⽅法Object.assign(),它实现浅拷贝有个条件,就是如果拷贝对的对象中存在引⽤数据类型,那它就是浅拷贝,如果不存在,那它就是深拷贝。使⽤⽅法如下:
2. 深拷贝 先介绍⼀下⼀些常⽤的API来实现深拷贝:
JSON.stringify 和 JSON.parse ⽤ JSON.stringify 把对象转换成字符串,再⽤ JSON.parse 把字符串转换成新的对象。使⽤条件是:可以转成 JSON 格式的对象才能使⽤这种⽅法,如果对象中包含 function 或 RegExp 这些就不能⽤这种⽅法了。  let  obj = {    name : 'lwf',    age : 18,    color : ['红⾊', '蓝⾊'],    like : {      game : '玩游戏',      sport : '打乒乓'    }  }  let  o = {}  Object .assign (o ,obj )  o .name = 'cll'  o .color .push ('绿⾊')  console .log (o );  console .log (obj );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17deepCopy  = (Obj ) => {    let  _obj = JSON .stringify (obj );    let  objClone = JSON .parse (_obj );    return  objClone ;  }  o = deepCopy (obj )  o .name = 'cll'  o .color .push ('绿⾊')  console .log (o );  console .log (obj );
1
2
3
4
5
6
7
8
9
10
11
12
输出结果可发现只有新的对象o 上⾯的属性值改变了,旧对象obj
上的值没有变化。
通过jQuery的extend⽅法实现深拷贝 由于⼯作中没有使⽤过jQuery和lodash,这种⽅式我没有具体使⽤过,放在这⾥做⼀个记录。
lodash.cloneDeep()实现深拷贝
使⽤递归的⽅式实现深拷贝 这个⽅式是⾯试官经常问的点,能⼿写就更好了。let  $ = require ('jquery');let  obj1 = {  a : 1,  b : {    f : {      g : 1    }  },  c : [1, 2, 3]};let  obj2 = $.extend (true , {}, obj1);
1
2
3
4
56
7
8
9
10
11let  _ = require ('lodash');let  obj1 = {    a : 1,    b : { f : { g : 1 } },    c : [1, 2, 3]};let  obj2 = _.cloneDeep (obj1);
1jquery框架面试题
2
3
4
5
6
7
输出结果和上⾯JSON⽅法⼀致:let  obj = {    name : 'lwf',    age : 18,    color : ['红⾊', '蓝⾊'],    like : {      game : '玩游戏',      sport : '打乒乓'    }  }  let  o = {}  //深拷贝  deepCopy  = (newObj , oldObj ) => {    //遍历旧的对象    for  (let  k in  oldObj ) {      //判断k 的值是不是数组,数组先判断是因为数组也是Object 类型      if  (oldObj [k ] instanceof  Array ) {        newObj [k ] = []        deepCopy (newObj [k ], oldObj [k ])      } else  if  (oldObj [k ] instanceof  Object ) { //判断是不是对象        newObj [k ] = {}        deepCopy (newObj [k ], oldObj [k ])      } else  {        newObj [k ] = oldObj [k ]      }    }  }    deepCopy (o , obj )  o .name = 'cll'  o .color .push ('绿⾊')  console .log (o );  console .log (obj );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。